Android快速开发偷懒必备一句话搞定所有ViewGroup的Adapter支持自定义ViewGroupWord下载.docx
- 文档编号:21058056
- 上传时间:2023-01-27
- 格式:DOCX
- 页数:23
- 大小:3.71MB
Android快速开发偷懒必备一句话搞定所有ViewGroup的Adapter支持自定义ViewGroupWord下载.docx
《Android快速开发偷懒必备一句话搞定所有ViewGroup的Adapter支持自定义ViewGroupWord下载.docx》由会员分享,可在线阅读,更多相关《Android快速开发偷懒必备一句话搞定所有ViewGroup的Adapter支持自定义ViewGroupWord下载.docx(23页珍藏版)》请在冰豆网上搜索。
*搭配一个工具类,为所有ViewGroupaddView。
*再封装出两个使用快速简单的Adapter分别用于添加
单一Item布局、多种Item布局。
PS:
所以本文也算是填了之前的一个坑,在之前文末,我就提到要写一篇为流式布局增加Adapter的文章,作为Adapter的实战演练。
使用本文封装的Adapter自然可以达到这一点。
由于采用Adapter隔离ViewGroup和ItemView,在切换ViewGroup时,十分方便。
如:
在需求让你把一个HorizontalScrollView包裹的水平标签转换成流式布局时,只需要在xml替换控件即可。
Adapter将自动完成适配的工作。
其他代码一句不用修改。
不BB了,先看看以后如何使用吧,够不够简单粗暴。
使用预览
单一Item类型:
Adapter泛型传入JavaBean,构造函数传入数据集和layout布局,一句代码搞定:
//单一ItemView
ViewGroupUtils.addViews(mLinearLayout,newSingleAdapter<
TestBean>
(this,mDatas,R.layout.item_test){
@Override
publicvoidonBindView(ViewGroupparent,ViewitemView,TestBeandata,intpos){
Glide.with(LinearLayoutActivity.this)
.load(data.getAvatar())
.into((ImageView)itemView.findViewById(R.id.ivAvatar));
((TextView)itemView.findViewById(R.id.tvName)).setText(data.getName());
}
});
效果:
以前会用ScrollView嵌套ListView,现在只要用ScrollView套LinearLayout即可,性能更佳。
多种Item类型:
多种Item类型分两种情况:
数据结构相同:
数据结构相同依然可以给Adapter传入泛型,避免强转:
//多种ItemViewType,但是数据结构相同,可以传入数据结构泛型,避免强转
ViewGroupUtils.addViews(linearLayout,newMulTypeAdapter<
MulTypeBean>
(this,initDatas()){
publicvoidonBindView(ViewGroupparent,ViewitemView,MulTypeBeandata,intpos){
((TextView)itemView.findViewById(R.id.tvWords)).setText(data.getName()+"
"
);
Glide.with(MulTypeActivity.this)
.into((ImageView)itemView.findViewById(ivAvatar));
数据结构不同:
如果数据结构不同,则不用传入泛型,但是使用时需要强转:
//多种Item类型:
数据结构不同不传泛型了使用时需要强转javaBean,判断ItemLayoutId
ViewGroupUtils.addViews((ViewGroup)findViewById(R.id.activity_mul_type_mul_bean),newMulTypeAdapter(this,datas){
publicvoidonBindView(ViewGroupparent,ViewitemView,IMulTypeHelperdata,intpos){
switch(data.getItemLayoutId()){
caseR.layout.item_mulbean_1:
MulBean1mulBean1=(MulBean1)data;
Glide.with(MulTypeMulBeanActivity.this)
.load(mulBean1.getUrl())
.into((ImageView)itemView);
break;
caseR.layout.item_mulbean_2:
MulBean2mulBean2=(MulBean2)data;
TextViewtv=(TextView)itemView;
tv.setText(mulBean2.getName());
数据结构:
publicclassMulBean1implementsIMulTypeHelper{
privateStringurl;
publicintgetItemLayoutId(){
returnR.layout.item_mulbean_1;
}
publicclassMulBean2implementsIMulTypeHelper{
privateStringname;
returnR.layout.item_mulbean_2;
Item1布局是一个ImageView,Item2布局是一个TextView
Item点击事件
item的点击和长按等事件,有两种方法设置,这里以点击事件为例,长按事件同理:
Adapter.onBindView()里设置
在Adapter.onBindView()方法里能拿到ItemView,自然就可以设置各种事件。
类似RecyclerView。
在这里设置优先级更高。
原因后文会提到。
@Override
publicvoidonBindView(ViewGroupparent,ViewitemView,finalMulTypeBeandata,intpos){
....
itemView.setOnClickListener(newView.OnClickListener(){
publicvoidonClick(Viewview){
Toast.makeText(mContext,"
onBindView里设置:
文字是:
+data.getName(),Toast.LENGTH_SHORT).show();
通过ViewGroupUtils设置
可以在ViewGroupUtils.addViews直接作为参数传入.
也可以用ViewGroupUtils.setOnItemClickListener()设置。
优先级比Adapter.onBindView()里设置低,原因后文会提到。
//设置OnItemClickListener
OnItemClickListeneronItemClickListener=newOnItemClickListener(){
publicvoidonItemClick(ViewGroupparent,ViewitemView,intposition){
Toast.makeText(MulTypeActivity.this,"
通过OnItemClickListener设置:
+position,Toast.LENGTH_SHORT).show();
};
//可以在`ViewGroupUtils.addViews`直接作为参数传入.\
ViewGroupUtils.addViews(linearLayout,adapter,onItemClickListener);
//或者也可以用`ViewGroupUtils.setOnItemClickListener()`设置
ViewGroupUtils.setOnItemClickListener(linearLayout,onItemClickListener);
看起来还是挺好的,嗯~至少我自己这么觉得,我个人比较喜欢这种0耦合,每一个库都像可组装拆卸的机关枪一样,拿起来就用。
而不是笨重功能繁多的重装坦克。
搭配我的得意之作,每次必安利的史上集成最简单侧滑菜单控件。
效果如下:
无特殊设置,仅仅替换ViewGroup为流式布局,替换Item根布局为的侧滑菜单库,能感受到这种0耦合的库的魅力了么。
23333333。
设计思路
下面就让我手摸手带大家实现它。
先看类图。
UML类图:
先简要概括
*我们的顶层接口IViewGroupAdapter暴露出两个方法供ViewGroup使用。
∙ViewGroupUtils
是为任意ViewGroup动态addView的工具类,只依赖于IViewGroupAdapter
接口即可完成工作。
∙BaseAdapter是第二层,在这一层引入了数据集,用List<
T>
保存。
实现IViewGroupAdapter的方法,重载一个三参数的getView()方法,供子类去实现。
∙SingleAdapter是第三层,一个简化的Adapter,只支持单种Item,以LayoutId构建View。
实现getView()方法,并暴露出onBindView()供用户快速使用。
∙MulTypeAdapter也同处第三层,一个支持多种Item的Adapter。
依赖IMulTypeHelper接口,利用其getItemLayoutId()
方法去实现getView()方法,并暴露出onBindView()供用户快速使用。
顶层接口设计
顶层接口,即IViewGroupAdapter。
根据迪米特法则(最少知道原则),我们应该抽象出一个顶层的接口,对ViewGroup暴露出最少的方法供使用。
我们想一下,对于ViewGroup,它最少只需要哪些就能完成我们的需求。
*ChildView是什么—>
View
*有多少ChildView需要添加—>
count
所以,我们的最顶层接口如下编写:
publicinterfaceIViewGroupAdapter{
/**
*ViewGroup调用获取ItemView
*
*@paramparent
*@parampos
*@return
*/
ViewgetView(ViewGroupparent,intpos);
*ViewGroup调用,得到ItemCount
intgetCount();
ok,代码写到这里,后面的我们暂且不提,我们就可以写动态addView的工具类了。
因为我们的ViewGroup依赖的所有信息都由IViewGroupAdapter这个接口提供了。
工具类
ViewGroupUtils
是为任意ViewGroup动态addView的工具类,不考虑点击事件的情况下,只依赖于
IViewGroupAdapter
如下编写:
*为任意ViewGroup添加ItemViews.
*@paramviewGroup必传
*@paramadapter必传,至少提供要add的View和需要add的count
*@paramremoveViews是否需要remove掉之前的Views
publicstaticvoidaddViews(finalViewGroupviewGroup,IViewGroupAdapteradapter
booleanremoveViews){
if(viewGroup==null||adapter==null){
return;
//如果需要remove掉之前的Views
if(removeViews&
&
viewGroup.getChildCount()>
0){
viewGveAllViews();
//开始添加子Views,通过Adapter获得需要添加的Count
intcount=adapter.getCount();
for(inti=0;
i<
count;
i++){
//通过Adapter获得ItemView
ViewitemView=adapter.getView(viewGroup,i);
viewGroup.addView(itemView);
如此即可完成动态给任意ViewGroupaddView的工作。
不过我们开头提过,我还是想引入ItemView的点击和长按事件的。
但是关于这两个ItemListener,还是有一些东西要考虑的。
ItemListener的设计
为ViewGroup提供OnItemClickListener,有个问题需要考虑:
如果使用者调用了setOnItemClickListener,且在Adapter里自己又对ItemView设置了OnClickListener,那么究竟该触发哪个Listener,即它们的优先级。
我们不应该自己靠脑子想答案,还是参照系统原有的设计比较好。
既然ListView提供了OnItemClickListener,那么我们参照它的设计来就行。
先说结论:
通过参照ListView的源码,以及实验得知,对ItemView的OnClickListener优先级>
ViewGroup的OnItemClickListener。
为什么?
答案在源码中,感兴趣看,不感兴趣直接跳过。
从AbsListView的onTouchEvent()->
onTouchUp()->
PerformClick->
performItemClick->
AdapterView.performItemClick()
->
AdapterView.mOnItemClickListener,即可找到答案。
这里不详细分析源码,不是本文重点,简单的说,从入口处是AbsListView的onTouchEvent()
我们可以知道,ListView本身并没有干预ItemView的点击事件(即没有为其设置OnClickListener),是在ItemView不消耗Touch事件时才进行Item点击事件的触发。
因此若ItemView设置了OnClickListener,AbsListView的onTouchEvent()将收不到MotionEvent.ACTION_UP事件,因而也不会触发OnItemClickListener。
所以这决定了ItemView的OnClickListener优先级高。
还有一个问题,我们可以通过View.hasOnClickListeners()这个方法来判断View是否设置了OnClickListener,但是这个方法在API15才加入,为了能兼容低版本,我采用了另一种方法判断,itemView.isClickable(),如果true,我当做有点击事件,如果false,我当做没有。
其实在ListView中这个问题也是一样的,itemView.isClickable()为true的话,点击事件就被拦截住,不会分发至AbsListView的onTouchEvent()里了。
所以我们这么写是没问题,并且是正确的。
ItemListener的完整实现:
既然如此,那么我们在程序中,应该如下编写:
//添加点击事件
if(null!
=onItemClickListener&
!
itemView.isClickable()){
finalintnalI=i;
onItemClickListener.onItemClick(viewGroup,view,finalI);
=onItemLongClickListener&
itemView.isLongClickable()){
finalintfinalI=i;
itemView.setOnLongClickListener(newView.OnLongClickListener(){
publicbooleanonLongClick(Viewview){
returnonItemLongClickListener.onItemLongClick(viewGroup,view,finalI);
所以完整的addViews()如下:
*@paramonItemClickListenerItem点击事件
*@paramonItemLongClickListenerItem长按事件
booleanremoveViews
finalOnItemClickListeneronItemClickListener
finalOnItemLongClickListeneronItemLongClickListener){
viewGroup.removeAllViews();
//添加点击事件,itemView之前没有点击事件才会去设置
//添加长按事件itemView之前没有长按事件才会去设置
实际中,我们可能不需要设置Listener,为了快速使用,我又提供了两个重载方法:
*并且会清除掉之前所有add过的View
*@paramadapter
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android快速开发偷懒必备一句话搞定所有ViewGroup的Adapter 支持自定义ViewGroup Android 快速 开发 偷懒
链接地址:https://www.bdocx.com/doc/21058056.html