欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android recycleview(kotlin)实现上下滚动,类似中奖信息跑马灯

程序员文章站 2022-03-13 20:54:11
...

数据展示我们一般都是通过recycleview来处理,下面记录一下滚动需求的实现方法和步骤:

先看看效果:

Android recycleview(kotlin)实现上下滚动,类似中奖信息跑马灯

第一步:

新建一个实体类(Wininfo ):

 class Wininfo {
    var title: String? = null
    var test: String? = null

}

第二:新建revy的适配器(MyAdapterItem_auto):



/**
 * 适配器
 */
public class MyAdapterItem_auto extends RecyclerView.Adapter<MyAdapterItem_auto.ViewHolder> {

    List<Wininfo> list;
    Context context;
    private boolean bool;
    public MyAdapterItem_auto(List<Wininfo> list, Context context) {
        this.list = list;
        this.context = context;

    }

    //创建新View,被LayoutManager所调用
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_recywin, viewGroup, false);
        ViewHolder vh = new ViewHolder(view);
        return vh;
    }

    //将数据与界面进行绑定的操作
    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int position) {
        Wininfo wininfo = list.get(position);
        viewHolder.tv_title.setText(wininfo.getTitle() + ":\n");
        viewHolder.tv_test.setText(wininfo.getTest());

    }

    //获取数据的数量
    @Override
    public int getItemCount() {
           return list == null ? 0 : list.size();

    }

    //自定义的ViewHolder,持有每个Item的的所有界面元素
    class ViewHolder extends RecyclerView.ViewHolder {
        TextView tv_title, tv_test;  

        ViewHolder(View view) {
            super(view);
            tv_title = view.findViewById(R.id.tv_title);
            tv_test = view.findViewById(R.id.tv_test);

        }
    }
}

适配器里面的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="4"
        android:gravity="center"
        android:textSize="50sp"
        android:text="烧鸭饭"/>
    <TextView
        android:id="@+id/tv_test"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:textSize="50sp"

        android:text="恭喜手机尾号123xxxxxxxx中奖啦"/>
</LinearLayout>

 第三;重新自定义recycleview(AutoPollRecyclerView):

package com.example.test_01.recy;

import android.content.Context;


import android.util.AttributeSet;
import android.view.MotionEvent;

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

import java.lang.ref.WeakReference;

public class AutoPollRecyclerView extends RecyclerView {
    private static final long TIME_AUTO_POLL =1;
    AutoPollTask autoPollTask;
    private boolean running; //标示是否正在自动轮询
    private boolean canRun;//标示是否可以自动轮询,可在不需要的是否置false

    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<AutoPollRecyclerView>(reference);
        }

        @Override
        public void run() {
            AutoPollRecyclerView recyclerView = mReference.get();
            if (recyclerView != null && recyclerView.running && recyclerView.canRun) {
                recyclerView.scrollBy(2, 2);
                recyclerView.postDelayed(recyclerView.autoPollTask, recyclerView.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  false,注释掉onTouchEvent()方法里面的stop和start方法,则列表自动滚动且不可触摸
        return super.onTouchEvent(e);}
}

第四步 无缝数据底部回到顶部(RecyclerViewScrollHelper ):

public class RecyclerViewScrollHelper {
    public static void scrollToPosition(RecyclerView recyclerView, int position){
        RecyclerView.LayoutManager manager1 = recyclerView.getLayoutManager();
        if (manager1 instanceof LinearLayoutManager) {
            LinearLayoutManager manager = (LinearLayoutManager) manager1;
            final TopSmoothScroller mScroller = new TopSmoothScroller(recyclerView.getContext());
            mScroller.setTargetPosition(position);
            manager.startSmoothScroll(mScroller);
        }
    }

    public static class TopSmoothScroller extends LinearSmoothScroller {
        TopSmoothScroller(Context context) {
            super(context);
        }
        @Override
        protected int getHorizontalSnapPreference() {
            return SNAP_TO_START;
        }
        @Override
        protected int getVerticalSnapPreference() {
            return SNAP_TO_START;
        }
    }
}

第五步  新建测试的activity的布局(activity_recy):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:gravity="center"
    tools:context=".recy.RecyActivity">

    <com.example.test_01.recy.AutoPollRecyclerView
        android:id="@+id/recy01"
        android:layout_width="match_parent"
        android:layout_height="300dp"/>
</RelativeLayout>

第六步  activity测试:

package com.example.test_01.recy

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.test_01.R
import kotlinx.android.synthetic.main.activity_recy.*
import java.util.*

class RecyActivity : AppCompatActivity() {
    //滚动版
    var myAdapterItem_doctor_auto: MyAdapterItem_auto? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_recy)
        var list: MutableList<Wininfo>? = ArrayList()
        for (s in 0..9) {
            var tt = Wininfo()
            tt.test = "恭喜手机尾号18xxxxxx3541中奖"
            tt.title = "奶茶店$s"
            list!!.add(tt)
        }

        //垂直方向
        val linearLayoutManager = LinearLayoutManager(this)
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL)
        recy01.setLayoutManager(linearLayoutManager)
        myAdapterItem_doctor_auto = MyAdapterItem_auto(list, this) //滚动版

        recy01.setAdapter(myAdapterItem_doctor_auto)
        recy01.start()
        recy01.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)
            }

            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                if (isSlideToBottom(recyclerView)) {
                    // LogUtils.e("是否滑动到底部?" + isSlideToBottom(recyclerView) + "");
                    runOnUiThread(Runnable { // recy_doctor_all.scrollToPosition(0);
                        RecyclerViewScrollHelper.scrollToPosition(recy01, 0)
                    })
                }
            }


        })
    }

    private fun isSlideToBottom(recyclerView: RecyclerView?): Boolean {
        if (recyclerView == null) return false
        return if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset() >= recyclerView.computeVerticalScrollRange()) true else false
    }
}

 到这里就实现了滚动,虽然这不是最好的办法,我想要的是效果不用从底部跳到0项数据开始滚动,而是从最后一项直接拼接到首项0开始继续循环下去,如果你有更好的方式,评论留言交流一下,实现的方式。