组合控件——升级版翻页——下拉刷新布局SwipeRefreshLayout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- 注意SwipeRefreshLayout要使用全路径 -->
    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/srl_dynamic"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <!-- 注意RecyclerView要使用全路径 -->
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_dynamic"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</LinearLayout>

===================================================================================================

xml布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp">

    <!-- 注意SwipeRefreshLayout要使用全路径 -->
    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/srl_dynamic"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <!-- 注意RecyclerView要使用全路径 -->
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_dynamic"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#aaaaff" />
    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

</LinearLayout>

主代码:

package com.example.myapplication;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener;

import com.example.myapplication.adapter.LinearDynamicAdapter;
import com.example.myapplication.bean.NewsInfo;
import com.example.myapplication.widget.RecyclerExtras.OnItemClickListener;
import com.example.myapplication.widget.RecyclerExtras.OnItemDeleteClickListener;
import com.example.myapplication.widget.RecyclerExtras.OnItemLongClickListener;
import com.example.myapplication.widget.SpacesDecoration;

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

@SuppressLint("DefaultLocale")
public class MainActivity extends AppCompatActivity  implements OnRefreshListener, OnItemClickListener, OnItemLongClickListener, OnItemDeleteClickListener
{

    private SwipeRefreshLayout srl_dynamic; // 声明一个下拉刷新布局对象

    private RecyclerView rv_dynamic; // 声明一个循环视图对象

    private LinearDynamicAdapter mAdapter; // 声明一个线性适配器对象

    private List<NewsInfo> mPublicList = NewsInfo.getDefaultList(); // 当前的公众号信息列表

    private List<NewsInfo> mOriginList = NewsInfo.getDefaultList(); // 原始的公众号信息列表

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 从布局文件中获取名叫srl_dynamic的下拉刷新布局
        srl_dynamic = findViewById(R.id.srl_dynamic);

        srl_dynamic.setOnRefreshListener(this); // 设置下拉布局的下拉刷新监听器

        // 设置下拉刷新布局的进度圆圈颜色
        srl_dynamic.setColorSchemeResources(R.color.red, R.color.orange, R.color.green, R.color.blue);

        initRecyclerDynamic(); // 初始化动态线性布局的循环视图
    }

    // 初始化动态线性布局的循环视图
    private void initRecyclerDynamic()
    {

        // 从布局文件中获取名叫rv_dynamic的循环视图
        rv_dynamic = findViewById(R.id.rv_dynamic);

        // 创建一个垂直方向的线性布局管理器
        LinearLayoutManager manager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);

        rv_dynamic.setLayoutManager(manager); // 设置循环视图的布局管理器

        // 构建一个公众号列表的线性适配器
        mAdapter = new LinearDynamicAdapter(this, mPublicList);

        mAdapter.setOnItemClickListener(this); // 设置线性列表的点击监听器
        mAdapter.setOnItemLongClickListener(this); // 设置线性列表的长按监听器
        mAdapter.setOnItemDeleteClickListener(this); // 设置线性列表的删除按钮监听器
        rv_dynamic.setAdapter(mAdapter);  // 设置循环视图的线性适配器
        rv_dynamic.setItemAnimator(new DefaultItemAnimator());  // 设置循环视图的动画效果
        rv_dynamic.addItemDecoration(new SpacesDecoration(1));  // 设置循环视图的空白装饰
    }

    // 一旦在下拉刷新布局内部往下拉动页面,就触发下拉监听器的onRefresh方法
    public void onRefresh()
    {

        mHandler.postDelayed(mRefresh, 2000); // 模拟网络耗时,延迟若干秒后启动刷新任务
    }

    private Handler mHandler = new Handler(Looper.myLooper()); // 声明一个处理器对象

    // 定义一个刷新任务
    private Runnable mRefresh = new Runnable()
    {

        @Override
        public void run()
        {

            srl_dynamic.setRefreshing(false); // 结束下拉刷新布局的刷新动作

            int position = new Random().nextInt(mOriginList.size()-1); // 获取一个随机位置

            NewsInfo old_item = mOriginList.get(position);

            NewsInfo new_item = new NewsInfo(old_item.pic_id, old_item.title, old_item.desc);

            mPublicList.add(0, new_item); // 在顶部添加一条公众号消息

            mAdapter.notifyItemInserted(0); // 通知适配器列表在第一项插入数据

            rv_dynamic.scrollToPosition(0); // 让循环视图滚动到第一项所在的位置

            // 当循环视图的列表项已经占满整个屏幕时,再往顶部添加一条新记录,
            // 感觉屏幕没有发生变化,也没看到插入动画。
            // 此时就要调用scrollToPosition(0)方法,表示滚动到第一条记录。
        }
    };

    // 一旦点击循环适配器的列表项,就触发点击监听器的onItemClick方法
    public void onItemClick(View view, int position)
    {

        String desc = String.format("您点击了第%d项,标题是%s", position + 1,
                mPublicList.get(position).title);
        Toast.makeText(this, desc, Toast.LENGTH_SHORT).show();
    }

    // 一旦长按循环适配器的列表项,就触发长按监听器的onItemLongClick方法
    public void onItemLongClick(View view, int position)
    {

        NewsInfo item = mPublicList.get(position);
        item.isPressed = !item.isPressed;
        mPublicList.set(position, item);
        mAdapter.notifyItemChanged(position); // 通知适配器列表在第几项发生变更
    }

    // 一旦点击循环适配器列表项的删除按钮,就触发删除监听器的onItemDeleteClick方法
    public void onItemDeleteClick(View view, int position)
    {

        mPublicList.remove(position);
        mAdapter.notifyItemRemoved(position); // 通知适配器列表在第几项删除数据
    }

}
SpacesDecoration
package com.example.myapplication.widget;

import android.graphics.Rect;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;

public class SpacesDecoration extends RecyclerView.ItemDecoration
{

    private int space; // 空白间隔

    public SpacesDecoration(int space)
    {

        this.space = space;
    }

    @Override
    public void getItemOffsets(Rect outRect, View v, RecyclerView parent, RecyclerView.State state)
    {

        outRect.left = space; // 左边空白间隔
        outRect.right = space; // 右边空白间隔
        outRect.bottom = space; // 上方空白间隔
        outRect.top = space; // 下方空白间隔

    }

}
RecyclerExtras
package com.example.myapplication.widget;

import android.view.View;

public class RecyclerExtras
{

    // 定义一个循环视图列表项的点击监听器接口
    public interface OnItemClickListener
    {
        void onItemClick(View view, int position);

    }

    // 定义一个循环视图列表项的长按监听器接口
    public interface OnItemLongClickListener
    {

        void onItemLongClick(View view, int position);
    }

    // 定义一个循环视图列表项的删除监听器接口
    public interface OnItemDeleteClickListener 
    {
        void onItemDeleteClick(View view, int position);
    }

}
NewsInfo
package com.example.myapplication.bean;

import com.example.myapplication.R;
import java.util.ArrayList;
import java.util.List;

public class NewsInfo
{

    public int pic_id; // 图片的资源编号
    public String title; // 标题
    public String desc; // 描述
    public boolean isPressed; // 是否按下
    public int id; // 商品信息编号
    private static int seq = 0; // 序号

    public NewsInfo(int pic_id, String title, String desc)
    {

        this.pic_id = pic_id;
        this.title = title;
        this.desc = desc;
        this.isPressed = false;
        this.id = this.seq;
        this.seq++;
    }

    private static int[] newsImageArray = {R.drawable.public_01, R.drawable.public_02
            , R.drawable.public_03, R.drawable.public_04, R.drawable.public_05};

    private static String[] newsTitleArray = {
            "首都日报", "海峡时报", "东方周末", "参照消息", "挨踢杂志"};

    private static String[] newsDescArray = {
            "北京冬奥精彩纷呈,中外健儿各显神通",
            "庆祝伟大统一,闽台两地合办中秋晚会",
            "日本新娘仰慕中土,纷纷跨海嫁往上海",
            "雅万高铁建成通车,中国标准再下一城",
            "Mate40大战iPhone12,两大豪机争上游"};

    public static List<NewsInfo> getDefaultList()
    {

        List<NewsInfo> newsList = new ArrayList<NewsInfo>();
        for (int i = 0; i < newsImageArray.length; i++) {
            newsList.add(new NewsInfo(newsImageArray[i], newsTitleArray[i], newsDescArray[i]));
        }
        return newsList;
    }

    private static int[] gridImageArray = {R.drawable.pic_01, R.drawable.pic_02, R.drawable.pic_03
            , R.drawable.pic_04, R.drawable.pic_05, R.drawable.pic_06, R.drawable.pic_07
            , R.drawable.pic_08, R.drawable.pic_09, R.drawable.pic_10};

    private static String[] gridTitleArray = {"商场", "超市", "百货", "便利店",
            "地摊", "食杂店", "饭店", "餐厅", "会所", "菜市场"};

    public static List<NewsInfo> getDefaultGrid() {
        List<NewsInfo> gridList = new ArrayList<NewsInfo>();
        for (int i = 0; i < gridImageArray.length; i++) {
            gridList.add(new NewsInfo(gridImageArray[i], gridTitleArray[i], null));
        }
        return gridList;
    }

    private static int[] stagImageArray = {R.drawable.skirt01, R.drawable.skirt02, R.drawable.skirt03
            , R.drawable.skirt04, R.drawable.skirt05, R.drawable.skirt06, R.drawable.skirt07
            , R.drawable.skirt08, R.drawable.skirt09, R.drawable.skirt10, R.drawable.skirt11
            , R.drawable.skirt12, R.drawable.skirt13, R.drawable.skirt14, R.drawable.skirt15
            , R.drawable.skirt16, R.drawable.skirt17, R.drawable.skirt18, R.drawable.skirt19
            , R.drawable.skirt20, R.drawable.skirt21, R.drawable.skirt22, R.drawable.skirt23};

    private static String[] stagTitleArray = {"促销价", "惊爆价", "跳楼价", "白菜价", "清仓价", "割肉价",
            "实惠价", "一口价", "满意价", "打折价", "腰斩价", "无人问津", "算了吧", "大声点",
            "嘘嘘", "嗯嗯", "呼呼", "呵呵", "哈哈", "嘿嘿", "嘻嘻", "嗷嗷", "喔喔"};

    public static List<NewsInfo> getDefaultStag() {
        List<NewsInfo> stagList = new ArrayList<NewsInfo>();
        for (int i = 0; i < stagImageArray.length; i++) {
            stagList.add(new NewsInfo(stagImageArray[i], stagTitleArray[i], null));
        }
        return stagList;
    }

    private static int[] combineImageArray = {R.drawable.cainixihuan, R.drawable.dapaijiadao
            , R.drawable.trip_01, R.drawable.trip_02, R.drawable.trip_03, R.drawable.trip_04};
    private static String[] combineTitleArray = {
            "猜你喜欢", "大牌驾到", "买哪个", "别想了", "先下单", "包你满意"};

    public static List<NewsInfo> getDefaultCombine() {
        List<NewsInfo> combineList = new ArrayList<NewsInfo>();
        for (int i = 0; i < combineImageArray.length; i++) {
            combineList.add(new NewsInfo(combineImageArray[i], combineTitleArray[i], null));
        }
        return combineList;
    }

    private static int[] appiImageArray = {R.drawable.dian01, R.drawable.dian02, R.drawable.dian03
            , R.drawable.dian04, R.drawable.dian05, R.drawable.dian06, R.drawable.dian07
            , R.drawable.dian08, R.drawable.dian09, R.drawable.dian10, R.drawable.dian11
            , R.drawable.dian12, R.drawable.dian13, R.drawable.dian14, R.drawable.dian15};
    private static String[] appiTitleArray = {"双十一", "大聚惠", "爆款价",
            "就一次", "手慢无", "快点击", "付定金", "享特权", "包安装", "再返券",
            "白送你", "想得美", "干活去", "好好学", "才有钱"};

    public static List<NewsInfo> getDefaultAppi() {
        List<NewsInfo> appiList = new ArrayList<NewsInfo>();
        for (int i = 0; i < appiImageArray.length; i++) {
            appiList.add(new NewsInfo(appiImageArray[i], appiTitleArray[i], null));
        }
        return appiList;
    }

}
LinearDynamicAdapter
package com.example.myapplication.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import com.example.myapplication.R;
import com.example.myapplication.bean.NewsInfo;
import com.example.myapplication.widget.RecyclerExtras.OnItemClickListener;
import com.example.myapplication.widget.RecyclerExtras.OnItemDeleteClickListener;
import com.example.myapplication.widget.RecyclerExtras.OnItemLongClickListener;
import java.util.List;

public class LinearDynamicAdapter extends RecyclerView.Adapter<ViewHolder> implements View.OnClickListener, View.OnLongClickListener
{

    private final static String TAG = "LinearDynamicAdapter";
    private Context mContext; // 声明一个上下文对象
    private List<NewsInfo> mPublicList;

    public LinearDynamicAdapter(Context context, List<NewsInfo> publicList)
    {

        mContext = context;
        mPublicList = publicList;
    }

    // 获取列表项的个数
    public int getItemCount()
    {

        return mPublicList.size();
    }

    // 创建列表项的视图持有者
    public ViewHolder onCreateViewHolder(ViewGroup vg, int viewType)
    {

        // 根据布局文件item_linear.xml生成视图对象
        View v = LayoutInflater.from(mContext).inflate(R.layout.item_linear, vg, false);
        return new ItemHolder(v);
    }

    // 根据列表项编号获取当前的位置序号
    private int getPosition(int item_id)
    {

        int pos = 0;
        for (int i = 0; i < mPublicList.size(); i++)
        {

            if (mPublicList.get(i).id == item_id)
            {

                pos = i;
                break;
            }
        }
        return pos;
    }

    private int CLICK = 0; // 正常点击
    private int DELETE = 1; // 点击了删除按钮

    @Override
    public void onClick(View v)
    {

        int position = getPosition((int) v.getId() / 10);
        int type = (int) v.getId() % 10;
        if (type == CLICK) { // 正常点击,则触发点击监听器的onItemClick方法
            if (mOnItemClickListener != null)
            {

                mOnItemClickListener.onItemClick(v, position);
            }
        }
        else if (type == DELETE)  // 点击了删除按钮,则触发删除监听器的onItemDeleteClick方法
        {
            if (mOnItemDeleteClickListener != null)
            {
                mOnItemDeleteClickListener.onItemDeleteClick(v, position);
            }
        }
    }

    @Override
    public boolean onLongClick(View v) { // 长按了列表项,则调用长按监听器的onItemLongClick方法
        int position = getPosition((int) v.getId() / 10);
        if (mOnItemLongClickListener != null) {
            mOnItemLongClickListener.onItemLongClick(v, position);
        }
        return true;
    }

    // 绑定列表项的视图持有者
    public void onBindViewHolder(ViewHolder vh, final int position) {
        NewsInfo item = mPublicList.get(position);
        ItemHolder holder = (ItemHolder) vh;
        holder.iv_pic.setImageResource(item.pic_id);
        holder.tv_title.setText(item.title);
        holder.tv_desc.setText(item.desc);
        holder.tv_delete.setVisibility((item.isPressed) ? View.VISIBLE : View.GONE);
        holder.tv_delete.setId(item.id * 10 + DELETE);
        holder.tv_delete.setOnClickListener(this);
        holder.ll_item.setId(item.id * 10 + CLICK);
        // 列表项的点击事件需要自己实现
        holder.ll_item.setOnClickListener(this);
        // 列表项的长按事件需要自己实现
        holder.ll_item.setOnLongClickListener(this);
    }

    // 获取列表项的类型
    public int getItemViewType(int position) {
        return 0;
    }

    // 获取列表项的编号
    public long getItemId(int position) {
        return position;
    }

    // 定义列表项的视图持有者
    public class ItemHolder extends ViewHolder {
        public LinearLayout ll_item; // 声明列表项的线性布局
        public ImageView iv_pic; // 声明列表项图标的图像视图
        public TextView tv_title; // 声明列表项标题的文本视图
        public TextView tv_desc; // 声明列表项描述的文本视图
        public TextView tv_delete; // 声明列表项删除按钮的文本视图

        public ItemHolder(View v) {
            super(v);
            ll_item = v.findViewById(R.id.ll_item);
            iv_pic = v.findViewById(R.id.iv_pic);
            tv_title = v.findViewById(R.id.tv_title);
            tv_desc = v.findViewById(R.id.tv_desc);
            tv_delete = v.findViewById(R.id.tv_delete);
        }

    }

    // 声明列表项的点击监听器对象
    private OnItemClickListener mOnItemClickListener;

    public void setOnItemClickListener(OnItemClickListener listener) {
        this.mOnItemClickListener = listener;
    }

    // 声明列表项的长按监听器对象
    private OnItemLongClickListener mOnItemLongClickListener;

    public void setOnItemLongClickListener(OnItemLongClickListener listener) {
        this.mOnItemLongClickListener = listener;
    }

    // 声明列表项的删除监听器对象
    private OnItemDeleteClickListener mOnItemDeleteClickListener;

    public void setOnItemDeleteClickListener(OnItemDeleteClickListener listener) {
        this.mOnItemDeleteClickListener = listener;
    }

}

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值