Android 通知消息水平播放、无限循环效果实现

今天我们来实现一个简单的效果,通知消息无限循环播放,先看效果图:

这里写图片描述

这个效果也很常见,实现的方法也有很多,我是使用RecyclerView来实现的,觉得还是挺不错的,就写下来分享给大家。 
下面先看我们的布局文件main.xml,里面主要是一个RecyclerView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
   <android.support.v7.widget.RecyclerView
       android:id="@+id/myRecyclerView"
       android:layout_width="match_parent"
       android:layout_height="36dp"
       android:layout_marginTop="20dp"
       android:background="#faf7bb"
       >
   </android.support.v7.widget.RecyclerView>
</LinearLayout>

接下来看一下MainActivity的代码:

public class MainActivity extends Activity {

    @BindView(R.id.myRecyclerView)RecyclerView myRecyclerView;
    private List<String> mDatas;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ButterKnife.bind(this);
        initData();
        initView();
    }
    private void initData(){
        mDatas = new ArrayList<>();
        mDatas.add("我被青春撞了一下腰");
        mDatas.add("爱就一个字,我只说一次");
        mDatas.add("你在他乡还好吗");
    }
    private void initView(){
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false);
        myRecyclerView.setLayoutManager(linearLayoutManager);
        myRecyclerView.setAdapter(new MyAdapter());
        handler.sendEmptyMessageDelayed(0x00,1000);
    }

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            myRecyclerView.scrollBy(myRecyclerView.getScrollX()+2,myRecyclerView.getScrollY());
            handler.sendEmptyMessageDelayed(0x00,100);
        }
};
}

再看一下Adapter:

class MyAdapter extends RecyclerView.Adapter<MyViewHolder>{

        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new MyViewHolder(LayoutInflater.from(MainActivity.this).inflate(R.layout.item_recyclerview,parent,false));
        }

        @Override
        public void onBindViewHolder(MyViewHolder holder, final int position) {
            final  int tempPos = position%(mDatas.size());
            holder.textView.setText(mDatas.get(tempPos));
            holder.textView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast toast =    Toast.makeText(MainActivity.this,mDatas.get(tempPos),Toast.LENGTH_SHORT);
                    toast.setGravity(Gravity.CENTER,0,0);
                    toast.show();
                }
            });
        }

        @Override
        public int getItemCount() {
            return 100000;
        }
    }

    class MyViewHolder extends RecyclerView.ViewHolder{
        private TextView textView;
        public MyViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.tv_recyclerview);
        }
}

首先,创建一个List,存放播放的数据,然后设置RecyclerView, 
我们看一下MyAdapter,在getItemCount()方法里,我们返回的次数是100000,目的就是为了让数据大一点,看似达到了无限播放的效果,毕竟用户在一个界面的停留时间是有限的,这个根据具体业务场景,还可以适当调整。在看一下MainActivity的initView方法,设置好了RecyclerView之后,使用handler发送一个空消息,到达handler的handleMessage方法,这个方法的处理,就是我们的核心了, 
myRecyclerView.scrollBy(myRecyclerView.getScrollX()+2,myRecyclerView.getScrollY()); 
使用scroolBy,每隔100毫秒发送一次消息,每次scrollX增加2个像素位移,即可达到无限循环滚动的效果,好神奇。到此我们的功能就实现了。

下面做两个优化: 
1.第一个优化,

当页面有跳转时,禁止消息滚动,即暂停,当页面回来的时候再接着滚动。 
我们定义一个boolean类型的变量,在onStop和onRestart方法里分别赋值,

private boolean flag;
    @Override
    protected void onRestart() {
        flag = false;
        handler.sendEmptyMessageDelayed(0x00,100);
        super.onRestart();
    }
    @Override
    protected void onStop() {
        flag = true;
        super.onStop();
    }

接着,handler的handlerMessage方法稍微也改一下:

        @Override
        public void handleMessage(Message msg) {
            myRecyclerView.scrollBy(myRecyclerView.getScrollX() + 2, myRecyclerView.getScrollY());
            if (!flag) {
                handler.sendEmptyMessageDelayed(0x00, 100);
            }
        }

这样,在页面进行切换时,消息不再滚动了。

2.第二个优化,

扫描二维码关注公众号,回复: 2275270 查看本文章

禁止手动滚动消息,最上面那个效果图,可以看出,我们可以用手滚动消息,如果不想让用户用手滚动,则禁止响应move事件即可,由我们的布局文件可知,RecyclerView的父布局是LinearLayout,我们可以自定义LinearLayout,拦截掉move事件即可,代码如下:

public class ForbidMoveLinearLayout extends LinearLayout {
    public ForbidMoveLinearLayout(Context context) {
        super(context);
    }

    public ForbidMoveLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ForbidMoveLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_MOVE){
            return true;
        }
        return super.onInterceptTouchEvent(ev);
    }
}

我们的布局文件进行相应调整:

<?xml version="1.0" encoding="utf-8"?>
<com.example.administrator.helloapplication.ForbidMoveLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
   <android.support.v7.widget.RecyclerView
       android:id="@+id/myRecyclerView"
       android:layout_width="match_parent"
       android:layout_height="36dp"
       android:layout_marginTop="20dp"
       android:background="#faf7bb"
       >
   </android.support.v7.widget.RecyclerView>
</com.example.administrator.helloapplication.ForbidMoveLinearLayout>

这样就禁止手动滑动了,效果图就不贴了,可以自己试一下。看起来也不是那么难,但是如果想不到这个思路,就不好下手了。 
Ok,到此结束。

猜你喜欢

转载自blog.csdn.net/taa1007/article/details/81110746