三三要成為安卓糕手
引入:在上一篇文章中我們完成了新聞展示頁面多布局案例的展示,感悟頗多,本篇文章,繼續去開發一些新的功能
一:關閉廣告
所有的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() {@Overridepublic 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 {@Overrideprotected 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic void onSimpleItemClick(int position, Article article) {Toast.makeText(ArticleMoreListActivity.this,"跳轉到單張圖片對應的新聞資訊",Toast.LENGTH_SHORT).show();startActivity(new Intent(ArticleMoreListActivity.this, ArticleDetailActivity.class));}@Overridepublic void OnLongClickItem2Click(int position, Article article) {Toast.makeText(ArticleMoreListActivity.this,"你長按了2張圖片對應的布局",Toast.LENGTH_SHORT).show();}@Overridepublic 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);
@Overridepublic void onSimpleItemClick(int position, Article article) {Toast.makeText(ArticleMoreListActivity.this,"跳轉到單張圖片對應的新聞資訊",Toast.LENGTH_SHORT).show();startActivity(new Intent(ArticleMoreListActivity.this, ArticleDetailActivity.class));}@Overridepublic void OnLongClickItem2Click(int position, Article article) {Toast.makeText(ArticleMoreListActivity.this,"你長按了2張圖片對應的布局",Toast.LENGTH_SHORT).show();}@Overridepublic void onAdClick(int position, Article article) {Toast.makeText(ArticleMoreListActivity.this,"準備前往廣告詳細頁面",Toast.LENGTH_SHORT).show();}