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

发布于:2025-08-16 ⋅ 阅读:(20) ⋅ 点赞:(0)

在这里插入图片描述

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

一:关闭广告

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

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

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1:需求

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

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

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作为跳转后的页面

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 的所有子控件

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)定义接口

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)设计构造方法和定义成员变量

private ArticleItemCallBack articleItemCallBack;

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

	public ArticleMoreAdapter(ArticleItemCallBack articleItemCallBack) {
        this.articleItemCallBack = articleItemCallBack;
    }

(3)Holder中事件监听设置

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);
                }
            });
        }

效果:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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);
                }
            });
        }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

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

		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

public class ArticleMoreListActivity extends AppCompatActivity implements ArticleMoreAdapter.ArticleItemCallBack 
//设置适配器
        ArticleMoreAdapter adapter = new ArticleMoreAdapter(this);

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

网站公告

今日签到

点亮在社区的每一天
去签到