Android recyclerview 无限循环居中并自动向下滚动

Android recyclerview 无限循环居中并自动向下滚动

描述:这是一个基于recyclerview实现的 Android 无限循环滚动Demo,可自定义item。

项目代码在最后面!!!!跳转到最后

控件效果如下:

此控件为Android 无限循环居中并可以自动向下滚动。
请添加图片描述

实现功能:

  • 上下滚动无限循环(跳转回之前相似的postion)
  • 自动滚动
  • 利用flex可进行流式内容布局

设计核心:

主要的设计核心是依赖于recyclerview进行设计的,主要通过重写layoutmanager,Adapter,RecyclerView等来实现

核心代码:

CycleFlexManager .java
根据数量进行高度调整

package com.ui.design.view.automeasurelinear.linearmanager;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.recyclerview.widget.RecyclerView;

import com.google.android.flexbox.FlexboxLayoutManager;

/**
 * 流式布局
 */
public class CycleFlexManager extends FlexboxLayoutManager {
    
    
    private RecyclerView mRecyclerView;
    private int mItemViewHeight = 0;

    public CycleFlexManager(Context context, RecyclerView recyclerView) {
    
    
        super(context);

        this.mRecyclerView = recyclerView;
    }

    public CycleFlexManager(Context context, int flexDirection) {
    
    
        super(context, flexDirection);
    }

    public CycleFlexManager(Context context, int flexDirection, int flexWrap) {
    
    
        super(context, flexDirection, flexWrap);
    }

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

    /**
     * 添加LinearSnapHelper
     */
    @Override
    public void onAttachedToWindow(RecyclerView view) {
    
    
        super.onAttachedToWindow(view);
    }


    /**
     * 当滑动停止时触发回调 无限向下滚动
     */
    @Override
    public void onScrollStateChanged(int state) {
    
    
        super.onScrollStateChanged(state);
        if (state == 0) {
    
    

            int topposition = findFirstVisibleItemPosition();
            int lastpostion = findLastCompletelyVisibleItemPosition();
            Log.e("TEST", "findFirstVisibleItemPosition" + topposition);
            Log.e("TEST", "findLastVisibleItemPosition" + lastpostion);

            if (lastpostion > getItemCount() - 5) {
    
    //有些View可能转载比较多item 用顶部的postion来指示
                int prepostion = lastpostion - getItemCount() / 2;
                Log.e("TEST", "childconut" + prepostion);
                // View view=findViewByPosition(lastpostion);
                scrollToPosition(prepostion + 1); //找到可视图里第一个postion并让他向前移动一半
            }
            if (topposition == 0) {
    
    
                int prepostion = topposition + getItemCount() / 2;
                Log.e("TEST", "childconut" + prepostion);
                scrollToPosition(prepostion-1);
            }
        }
    }

    public int getmItemViewHeight() {
    
    
        if (mItemViewHeight==0){
    
    
            View view=findViewByPosition(0);
            if (view!=null){
    
    
                measureChildWithMargins(view, 0, 0);
                mItemViewHeight = view.getMeasuredHeight();
            }
        }
        return mItemViewHeight;
    }
}

AutoPollRecyclerView .java
自动滚动

package com.ui.design.view.automeasurelinear.recyclerview;


import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;


import com.ui.design.view.automeasurelinear.linearmanager.CycleFlexManager;

import java.lang.ref.WeakReference;

/**
 * 中间位置迁移
 */
public class AutoPollRecyclerView extends RecyclerView {
    
    

    private static final long TIME_AUTO_POLL = 16;
    AutoPollTask autoPollTask;
    private boolean running; //表示是否正在自动轮询
    private boolean canRun;//表示是否可以自动轮询

    public AutoPollRecyclerView(Context context, @Nullable AttributeSet attrs) {
    
    
        super(context, attrs);
        autoPollTask = new AutoPollTask(this);
    }

    static class AutoPollTask implements Runnable {
    
    
        private final WeakReference<AutoPollRecyclerView> mReference;

        //使用弱引用持有外部类引用->防止内存泄漏
        public AutoPollTask(AutoPollRecyclerView reference) {
    
    
            this.mReference = new WeakReference<>(reference);
        }

        @Override
        public void run() {
    
    
            AutoPollRecyclerView recyclerView = mReference.get();
            if (recyclerView.running && recyclerView.canRun) {
    
    
                recyclerView.scrollBy(2, 2);
                if (!recyclerView.canScrollVertically(5)){
    
    
                    if (recyclerView.getLayoutManager() instanceof CycleFlexManager){
    
    
                            ((CycleFlexManager)recyclerView.getLayoutManager()).onScrollStateChanged(0);//向无限循环manager释放不滚动信号 进行位置迁移
                    }
                }
                recyclerView.postDelayed(recyclerView.autoPollTask, TIME_AUTO_POLL);
            }
        }
    }

    //开启:如果正在运行,先停止->再开启
    public void start() {
    
    
        if (running)
            stop();
        canRun = true;
        running = true;
        postDelayed(autoPollTask, TIME_AUTO_POLL);
    }

    public void stop() {
    
    
        running = false;
        removeCallbacks(autoPollTask);
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
    
    
        switch (e.getAction()) {
    
    
            case MotionEvent.ACTION_DOWN:
                if (running)
                    stop();
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_OUTSIDE:
                if (canRun)
                    start();
                break;
        }
        return super.onTouchEvent(e);
    }

    private int cycleNum=4;

    public int getCycleNum() {
    
    
        return cycleNum;
    }

    public void setCycleNum(int cycleNum) {
    
    
        this.cycleNum = cycleNum;
    }


}

AutoMeasureAdapter.java 在Adapter中将size增加 不然无法实现无限循环滚动

package com.ui.design.view.automeasurelinear.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.alibaba.android.arouter.launcher.ARouter;
import com.ui.design.R;
import com.ui.design.main.bean.SelectorBean;
import com.ui.design.view.pickviewselect.view.PickerLayoutManager;

import java.util.List;

/**
 * 适配器
 * tangxianfeng
 * 2021.12.23
 */
public class AutoMeasureAdapter extends RecyclerView.Adapter<AutoMeasureAdapter.SViewHolder> {
    
    

    private final List<String> mList;
    private final Context mContext;
    private int mCycleNum=8;//长度重复次数 默认为8

    public AutoMeasureAdapter(Context context, List<String> stringList){
    
    
        this.mContext=context;
        this.mList=stringList;
    }
    @NonNull
    @Override
    public SViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    
    
        return new SViewHolder(LayoutInflater.from(mContext).inflate(R.layout.automeasure_adapter_item, parent,false));
    }

    @Override

    public void onBindViewHolder(@NonNull SViewHolder holder, int position) {
    
    

        if (mList == null || mList.size() == 0) {
    
    
            return;
        }
        holder.cardname.setText(mList.get(position % mList.size()));

    }

    @Override
    public int getItemCount() {
    
    
        if (mList == null||mList.size()==0) {
    
    
            return 0;
        }
        return  mList.size() * mCycleNum;//直接乘
    }

    static class SViewHolder extends RecyclerView.ViewHolder{
    
    

        private final TextView cardname;
        public SViewHolder(@NonNull View itemView) {
    
    
            super(itemView);
            cardname=(TextView) itemView.findViewById(R.id.card_name);
        }
    }


    public int getmCycleNum() {
    
    
        return mCycleNum;
    }

    public void setmCycleNum(int mCycleNum) {
    
    
        if (mCycleNum%2==1){
    
    
            mCycleNum++;//保证mCycleNum为2的倍数
        }
        this.mCycleNum = mCycleNum;
    }
}

使用示例:

AutomeasureActivity.java


package com.ui.design.view.automeasurelinear;

import androidx.recyclerview.widget.RecyclerView;

import com.alibaba.android.arouter.facade.annotation.Route;
import com.google.android.flexbox.FlexDirection;
import com.google.android.flexbox.JustifyContent;
import com.ui.design.R;
import com.ui.design.main.base.BaseActivity;
import com.ui.design.main.constants.Constants;
import com.ui.design.utils.RandomValue;
import com.ui.design.view.automeasurelinear.adapter.AutoMeasureAdapter;
import com.ui.design.view.automeasurelinear.linearmanager.CycleFlexManager;
import com.ui.design.view.automeasurelinear.recyclerview.AutoPollRecyclerView;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

@Route(path = Constants.AutomeasureActivity)
public class AutomeasureActivity extends BaseActivity {
    
    

    private List<String> stringList;
    @Override
    protected int initLayout() {
    
    
        return R.layout.activity_automeasure;
    }

    @Override
    protected void initView() {
    
    

        stringList=new ArrayList<>();

        for (int i=0;i<50;i++){
    
    
            stringList.add(RandomValue.getRandomContent());
        }

        AutoPollRecyclerView recyclerView=findViewById(R.id.auto_center);

        CycleFlexManager layoutManager = new CycleFlexManager(this,recyclerView);
        layoutManager.setFlexDirection(FlexDirection.ROW);//可设置排列
        layoutManager.setJustifyContent(JustifyContent.CENTER);//可设置是否居中
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.start();
        AutoMeasureAdapter autoMeasureAdapter = new AutoMeasureAdapter(this,stringList);
        recyclerView.setAdapter(autoMeasureAdapter);

    }

    @Override
    protected void initData() {
    
    

    }
}

activity_automeasure.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".view.automeasurelinear.AutomeasureActivity">

    <include layout="@layout/title_include"/>

    <com.ui.design.view.automeasurelinear.recyclerview.AutoPollRecyclerView
        android:id="@+id/auto_center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

项目代码仓库

如果直接复制可能会出现代码缺陷,完整代码请去仓库下载
如果觉得还行,耽误您几秒钟的时间去我的仓库点点star,万一以后用到了呢?

UIDesign 开源项目

猜你喜欢

转载自blog.csdn.net/number_cmd9/article/details/122226589