使用RecyclerView做类似ViewPager的效果实现app翻页公告

首先来看一下设计图,看到这个图其实我相信很多人直接就想到用ViewPager,用ViewPager绝对没问题,可是我比较懒,总觉得这个用ViewPager做不够轻量,于是乎百度,发现RecyclerView有一个辅助类PagerSnapHelper可以实现这种功能,于是乎试了一下,可是好像做下来也并没有我想的那么比ViewPager轻量,废话不多说了,记录一下,请大神多多指正。

使用RecyclerView做类似ViewPager的效果实现app翻页公告_第1张图片

主要是利用PagerSnapHelper的功能实现,代码如下:

final PagerSnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        switch (newState) {
            case RecyclerView.SCROLL_STATE_IDLE:
                View viewIdle = snapHelper.findSnapView(linearLayoutManager);
                if (viewIdle != null) {
                    int position = linearLayoutManager.getPosition(viewIdle);
                    updateIndicators(position);
                }
                break;
        }
    }
});

adapter = new RecyclerViewAdapter();
recyclerView.setAdapter(adapter);

RecyclerView本身的写发不变,只是这里这一点儿就能实现了,够简单了也是,可是有一个,有一些机型会把第二页的内容也显示到第一页,原因是有的机型会不加载itemView的顶层布局,所以顶层布局的match_parent不起作用,所以应该在adapter中给itemView动态设置宽度
public class ViewHolder extends RecyclerView.ViewHolder {
    private TextView textView;

    public ViewHolder(@NonNull View itemView) {
        super(itemView);
        float[] size = getDeviceDisplaySize(getContext());
        itemView.setMinimumWidth((int) size[0]);
        textView = itemView.findViewById(R.id.textView);
    }
}

因为我这里的是公告,childView只是一个可以上下滑动的TextView,这样就有了不同方向的滑动冲突,可以使用外部拦截的办法处理滑动冲突,自定义RecyclerView重写onInterceptTouchEvent 做下处理,代码如下:

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            startX = (int) event.getX();
            startY = (int) event.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            //如果左右滑动距离大于上下滑动距离,说明是RecyclerView在横向滑动,拦截事件自己处理,
             //否则就是TextView在上下滑动,就不拦截,交给TextView自己处理
            int dx = (int) (event.getX() - startX);
            int dy = (int) (event.getY() - startY);
            if (Math.abs(dx) > Math.abs(dy)) {
                return true;
            } else {
                return false;
            }
    }
    return super.onInterceptTouchEvent(event);
}

好了,就这样完了,完整代码如下:

public class NoticeDialog extends Dialog implements View.OnClickListener {

    private CustomerRecyclerView recyclerView;

    private LinearLayout indicatorContainer;
    private RecyclerViewAdapter adapter;

    public NoticeDialog(@NonNull Context context) {
        this(context, R.style.dialog);
    }

    public NoticeDialog(Context context, int themeResId) {
        super(context, themeResId);

        Window dialogWindow = getWindow();
        WindowManager.LayoutParams params = dialogWindow.getAttributes();
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        dialogWindow.setGravity(Gravity.CENTER);
        dialogWindow.setAttributes(params);
        setCanceledOnTouchOutside(false);

        initView();
    }

    private void initView() {
        View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_notice, null, false);
        setContentView(view);

        view.findViewById(R.id.btn_close).setOnClickListener(this);

        recyclerView = view.findViewById(R.id.recyclerView);
        indicatorContainer = view.findViewById(R.id.indicator_container);

        final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        recyclerView.setLayoutManager(linearLayoutManager);

        final PagerSnapHelper snapHelper = new PagerSnapHelper();
        snapHelper.attachToRecyclerView(recyclerView);
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                switch (newState) {
                    case RecyclerView.SCROLL_STATE_IDLE:
                        View viewIdle = snapHelper.findSnapView(linearLayoutManager);
                        if (viewIdle != null) {
                            int position = linearLayoutManager.getPosition(viewIdle);
                            updateIndicators(position);
                        }
                        break;
                }
            }
        });

        adapter = new RecyclerViewAdapter();
        recyclerView.setAdapter(adapter);
    }

    /**
     * 更新到当前指示器
     *
     * @param position
     */
    private void updateIndicators(int position) {
        for (int i = 0; i < indicatorContainer.getChildCount(); i++) {
            View childView = indicatorContainer.getChildAt(i);
            childView.setBackground(position == i ? getContext().getDrawable(R.drawable.shape_indicator_blue) : getContext().getDrawable(R.drawable.shape_indicator_gray));
        }
    }

    public void setNotices(List mDataSources) {
        adapter.setData(mDataSources);
        //当只有一页的时候不显示指示器
        if (mDataSources.size() <= 1) {
            return;
        }
        initIndicator(mDataSources);
    }

    /**
     * 添加滑动指示器
     *
     * @param mDataSources
     */
    private void initIndicator(List mDataSources) {
        indicatorContainer.removeAllViews();
        for (int i = 0; i < mDataSources.size(); i++) {
            View indicatorView = new View(getContext());
            indicatorView.setBackground(getContext().getDrawable(R.drawable.shape_indicator_gray));

            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(DensityUtils.dp2px(getContext(), 6), DensityUtils.dp2px(getContext(), 6));

            if (i != 0)
                layoutParams.leftMargin = DensityUtils.dp2px(getContext(), 8);
            indicatorView.setLayoutParams(layoutParams);
            indicatorContainer.addView(indicatorView);
        }
        updateIndicators(0);
    }

    @Override
    public void onClick(View v) {
        dismiss();
    }

    private class RecyclerViewAdapter extends RecyclerView.Adapter {

        private List mDataSources = new ArrayList<>();

        @NonNull
        @Override
        public RecyclerViewAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
            View view = LayoutInflater.from(getContext()).inflate(R.layout.customer_text_view, viewGroup, false);
            return new RecyclerViewAdapter.ViewHolder(view);
        }

        @Override
        public void onBindViewHolder(@NonNull RecyclerViewAdapter.ViewHolder viewHolder, int i) {
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
            viewHolder.textView.setLayoutParams(layoutParams);

            viewHolder.textView.setText(Html.fromHtml(mDataSources.get(i).context));
            viewHolder.textView.setMovementMethod(ScrollingMovementMethod.getInstance());
        }

        @Override
        public int getItemCount() {
            return mDataSources.size();
        }

        public class ViewHolder extends RecyclerView.ViewHolder {
            private TextView textView;

            public ViewHolder(@NonNull View itemView) {
                super(itemView);
                float[] size = getDeviceDisplaySize(getContext());
                itemView.setMinimumWidth((int) size[0]);
                textView = itemView.findViewById(R.id.textView);
            }
        }

        public void setData(List noticeList) {
            this.mDataSources.clear();
            this.mDataSources.addAll(noticeList);
            notifyDataSetChanged();
        }
    }

    public static float[] getDeviceDisplaySize(Context context) {
        Resources resources = context.getResources();
        DisplayMetrics dm = resources.getDisplayMetrics();
        int width = dm.widthPixels;
        int height = dm.heightPixels;

        float[] size = new float[2];
        size[0] = width;
        size[1] = height;

        return size;
    }
}

public class CustomerRecyclerView extends RecyclerView {

    private int startX, startY;

    public CustomerRecyclerView(@NonNull Context context) {
        this(context, null);
    }

    public CustomerRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomerRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startX = (int) event.getX();
                startY = (int) event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                //如果左右滑动距离大于上下滑动距离,说明是RecyclerView在横向滑动,
                //拦截事件自己处理,否则就是TextView在上下滑动,就不拦截,交给TextView自己处理
                int dx = (int) (event.getX() - startX);
                int dy = (int) (event.getY() - startY);
                if (Math.abs(dx) > Math.abs(dy)) {
                    return true;
                } else {
                    return false;
                }
        }
        return super.onInterceptTouchEvent(event);
    }
}

你可能感兴趣的:(Android,我的学习分享)