对方想着做一个跑马灯效果,而且要求内部的文字区域可以点击,我第一想到的就是RecyclerView来做,只要把getItemCount的返回值设置成无限大,就能实现循环滚动效果,滚动可以用scrollBy来实现。
先看MarqueeView类,继承与RecyclerView:
public class MarqueeView extends RecyclerView { Thread thread = null; AtomicBoolean shouldContinue = new AtomicBoolean(false); Handler mHandler; public MarqueeView(Context context) { super(context); } public MarqueeView(Context context, AttributeSet attrs) { super(context, attrs); } public MarqueeView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } private void init() { //主线程的handler,用于执行Marquee的滚动消息 mHandler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case 1://不论是竖直滚动还是水平滚动,都是偏移5个像素 MarqueeView.this.scrollBy(5, 5); break; } } }; if (thread == null) { thread = new Thread() { public void run() { while (shouldContinue.get()) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } Message msg=mHandler.obtainMessage(); msg.what=1; msg.sendToTarget(); } //退出循环时清理handler mHandler=null; } }; } } @Override /** * 在附到窗口的时候开始滚动 */ protected void onAttachedToWindow() { super.onAttachedToWindow(); shouldContinue.set(true); init(); thread.start(); } @Override /** * 在脱离窗口时处理相关内容 */ protected void onDetachedFromWindow() { super.onDetachedFromWindow(); stopMarquee(); } /** * 停止滚动 */ public void stopMarquee() { shouldContinue.set(false); thread = null; } /** * Adapter类 */public static class InnerAdapter extends Adapter{ private List mData; private int size; private LayoutInflater mLayoutInflater; public InnerAdapter(List data,Context context) { mData = data; size=mData.size(); mLayoutInflater=LayoutInflater.from(context); } @Override public MarqueHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view=mLayoutInflater.inflate(R.layout.marque_item,parent,false); return new MarqueHolder(view); } @Override public void onBindViewHolder(MarqueHolder holder, int position) { holder.tv.setText(mData.get(position%size)); } @Override public int getItemCount() { return Integer.MAX_VALUE; }/**** ViewHolder类**/ static class MarqueHolder extends ViewHolder { TextView tv; public MarqueHolder(View view) { super(view); tv = (TextView) view.findViewById(R.id.tv); } }} }
使用就很简单了,下面是MainActivity代码:
public class MainActivity extends AppCompatActivity {//初始化数据 private ArrayListdata = new ArrayList () { { add("第1条"); add("第2条"); add("第3条"); add("第4条"); add("第5条"); add("第6条"); add("第7条"); add("第8条"); add("第9条"); add("第10条"); add("第11条"); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MarqueeView marqueeView = (MarqueeView) findViewById(R.id.marqueView); LinearLayoutManager lm=new LinearLayoutManager(this); lm.setOrientation(LinearLayoutManager.HORIZONTAL); marqueeView.setLayoutManager(lm); marqueeView.setAdapter(new MarqueeView.InnerAdapter(data,this)); }}
两个layout文件,首先是Main的:
然后是item的:
至此运行效果如下: