【Android】适配器与外部事件的交互

三三要成为安卓糕手

引入:在上一篇文章中我们完成了新闻展示页面多布局案例的展示,感悟颇多,本篇文章,继续去开发一些新的功能

一:关闭广告

所有的view都可以和我们的用户做交互,循环视图中也给我们提供了相应的点击监听器

这是对整体做点击监听------缺点就是无法对内部单个控件进行监听

1:需求

点击关闭广告的字样后,广告关闭

思路:我们要找到广告对应的ViewHolder,在内部去找控件,进行监听,并处理关闭移除逻辑666

java 复制代码
public class AdViewHolder extends RecyclerView.ViewHolder {

        private final ImageView ivPicture;
        private final View ivClose;

        public AdViewHolder(@NonNull View itemView) {
            super(itemView);
            ivPicture = itemView.findViewById(R.id.iv_picture);
            ivClose = itemView.findViewById(R.id.tv_close);

            ivClose.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int layoutPosition = getLayoutPosition();
                    articles.remove(layoutPosition);
                    notifyItemRemoved(layoutPosition);
                }
            });
        }
    }

isClose对应的关闭广告这个控件,设置监听器,这里我们的Holder已经和position关联起来,此时在AdViewHolder中可以直接通过getLayoutPosition方法获取对应行号,战斗爽!

找到后,在数据源中直接移除(Position和index的位置恰好是一一对应的bro,在刷新一下item就OK了,思路还是非常清晰的

二:设置点击图片后跳转

问题:我现在点击广告,想要做的是跳转到广告页,或者是某个新闻的页面怎么做

以一张图片的为例,点击整个item都会进行跳转,所以是针对整体而非某个照片,文字

1:创建跳转后的Activity

创建一个新的Activity作为跳转后的页面

java 复制代码
public class ArticleDetailActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_article_detail);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });
    }
}

2:页面跳转思路

回想一下之前学过的页面跳转是怎么个事,好多地方都用到了。

提问:我们不是在ArticleMoreListActivity中进行跳转,而是在Adapter中进行页面跳转,Adapter又不是一个Activity,那怎么整?

解决思路:我们把ArticleMoreListActivity作为this参数,在适配器实例化的时候传参进去就OK了

这里我们在适配器类中提供构造方法进行参数接收,并创建成员变量,完成变量的初始化

activity.startActivity(new Intent(activity,ArticleDetailActivity.class); 这一句代码是关键

itemView 并不是指整个 item 中所包含的所有控件,而是指当前列表项(item)的根视图。可以理解成最外层视图容器,这个根视图容器内部包含了该 item 的所有子控件

java 复制代码
public class MyViewHolder extends RecyclerView.ViewHolder {

        private final ImageView ivPicture;
        private final TextView tvTitle;
        private final TextView tvAuthor;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            ivPicture = itemView.findViewById(R.id.iv_picture);
            tvTitle = itemView.findViewById(R.id.tv_title);
            tvAuthor = itemView.findViewById(R.id.tv_author);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
//                    int layoutPosition = getLayoutPosition();
//                    Article article = articles.get(layoutPosition);
                    activity.startActivity(new Intent(activity,ArticleDetailActivity.class));
                }
            });
        }
    }

3:接口回调思想------页面回调

提出问题:把activity往适配中传是一件不优雅的事情,一般我们不会再适配器中处理具体的业务逻辑,跳转页面啥的

解决关键:想办法把这个点击事件告诉外面的activity

直观一点也就是把左图的点击事件想办法告诉ArticleMoreListActivity

三:优雅写法

1:交互事件分析

  • 单个多个图片,点击页面跳转,长按,出现弹窗,不感兴趣,
  • 点击广告页面跳转

2:适配器中的工作

(1)定义接口

java 复制代码
public interface ArticleItemCallBack{
        /**
         * 点击一张图片
         * @param position
         * @param article
         */
        void onSimpleItemClick(int position , Article article);

        /**
         * 对两张图片的item做长按操作
         * @param position
         * @param article
         */
        void OnLongClickItem2Click(int position , Article article);

        /**
         * 点击广告
         * @param position
         * @param article
         */
        void onAdClick(int position , Article article);
    }

(2)设计构造方法和定义成员变量

java 复制代码
private ArticleItemCallBack articleItemCallBack;

也可以单独选择去创建一个方法调用

java 复制代码
	public ArticleMoreAdapter(ArticleItemCallBack articleItemCallBack) {
        this.articleItemCallBack = articleItemCallBack;
    }

(3)Holder中事件监听设置

java 复制代码
public MyViewHolder(@NonNull View itemView) {
            super(itemView);
         	/**
             * 对单张图片的item进行事件监听
             */
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int layoutPosition = getLayoutPosition();
                    Article article = articles.get(layoutPosition);
                    articleItemCallBack.onSimpleItemClick(layoutPosition,article);
                }
            });
        }

效果:

java 复制代码
public MyViewHolder2(@NonNull View itemView) {
            super(itemView);
            /**
             * 对两张图片的item进行点击监听
             */
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int layoutPosition = getLayoutPosition();
                    Article article = articles.get(layoutPosition);
                    articleItemCallBack.OnLongClickItem2Click(layoutPosition,article);
                }
            });
        }
java 复制代码
public AdViewHolder(@NonNull View itemView) {
            super(itemView);           
            /**
             * 对整个item容器进行监听
             */
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int layoutPosition = getLayoutPosition();
                    Article article = articles.get(layoutPosition);
                    articleItemCallBack.onAdClick(layoutPosition,article);
                }
            });
        }

3:Activity中的工作

(1)直接new CallBack 写法1

定义点击事件,看最上方的调用图就清楚流程了,这里的接口回调思想掌握住精髓了,真的感觉很奇妙

java 复制代码
		ArticleMoreAdapter adapter = new ArticleMoreAdapter(new ArticleMoreAdapter.ArticleItemCallBack() {
            @Override
            public void onSimpleItemClick(int position, Article article) {
                Toast.makeText(ArticleMoreListActivity.this,
                        "跳转到单张图片对应的新闻资讯",Toast.LENGTH_SHORT).show();
                startActivity(new Intent(ArticleMoreListActivity.this, ArticleDetailActivity.class));
            }

            @Override
            public void OnLongClickItem2Click(int position, Article article) {
                Toast.makeText(ArticleMoreListActivity.this,
                        "你长按了2张图片对应的布局",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onAdClick(int position, Article article) {
                Toast.makeText(ArticleMoreListActivity.this,
                        "准备前往广告详细页面",Toast.LENGTH_SHORT).show();
            }
        });

(2)this写法

等价写法,会显得代码更清爽;

类实现接口,类中重写方法,传参this即可666

java 复制代码
public class ArticleMoreListActivity extends AppCompatActivity implements ArticleMoreAdapter.ArticleItemCallBack 
java 复制代码
//设置适配器
        ArticleMoreAdapter adapter = new ArticleMoreAdapter(this);
java 复制代码
    @Override
    public void onSimpleItemClick(int position, Article article) {
        Toast.makeText(ArticleMoreListActivity.this,
                        "跳转到单张图片对应的新闻资讯",Toast.LENGTH_SHORT).show();
                startActivity(new Intent(ArticleMoreListActivity.this, ArticleDetailActivity.class));
    }

    @Override
    public void OnLongClickItem2Click(int position, Article article) {
                Toast.makeText(ArticleMoreListActivity.this,
                        "你长按了2张图片对应的布局",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onAdClick(int position, Article article) {
                Toast.makeText(ArticleMoreListActivity.this,
                        "准备前往广告详细页面",Toast.LENGTH_SHORT).show();
    }
相关推荐
德育处主任4 分钟前
p5.js 掌握圆锥体 cone
前端·数据可视化·canvas
mazhenxiao6 分钟前
qiankunjs 微前端框架笔记
前端
无羡仙13 分钟前
事件流与事件委托:用冒泡机制优化前端性能
前端·javascript
秃头小傻蛋13 分钟前
Vue 项目中条件加载组件导致 CSS 样式丢失问题解决方案
前端·vue.js
CodeTransfer13 分钟前
今天给大家搬运的是利用发布-订阅模式对代码进行解耦
前端·javascript
阿邱吖15 分钟前
form.item接管受控组件
前端
韩劳模17 分钟前
基于vue-pdf实现PDF多页预览
前端
鹏多多17 分钟前
js中eval的用法风险与替代方案全面解析
前端·javascript
KGDragon18 分钟前
还在为 SVG 烦恼?我写了个 CLI 工具,一键打包,性能拉满!(已开源)
前端·svg
LovelyAqaurius18 分钟前
JavaScript中的ArrayBuffer详解
前端