彻底理解RecyclerView的使用
文章目录0. 前言碎碎念1. 实现自定义复合组件效果1.1创建复合组件1.2 Activity中实现功能1.3 自定义控件实现制定组件的逻辑交互1.3.1 创建控件并绑定自定义组件1.3.2 实现交互逻辑2. 进阶ListView2.1 内置布局方式基础使用2.2 自定义布局方式0. 前言碎碎念安卓开发这些组件用来用去搞得人头都大了一会儿xml一会儿View一会儿又是ViewGroup的。在这里留个档以防未来自己又忘了。现在我所熟知的组件比如按钮、文本框、编辑框、乃至图片组件他们本质上都是一种view追溯到最上层他们都继承了View。常用的一些布局都是继承自ViewGroup的而继承自ViewGroup的这种特殊的View可以容纳其他的View组件从而形成“复合版本”的View这种符合版本的View本身又可以直接作为一个新的组件被加入到其他布局中使用如下这种形式即可调用包含include layoutlayout/布局xml文件名但是上述调用只能将复合组件SubXml加入另一个布局MainXml里面但是复合组件里面的子组件无法互动。为什么呢因为组件只是显示了出来他后面并没有逻辑代码来支撑他们。我们当然可以在MainActivity中通过findViewById()来找到对应的组件并为其设置逻辑行为代码比如监听点击或者其他的行为。但这样就显得很臃肿了我们想要的效果是自己定义一个复合组件这个组件可以直接被包含复用这个组件自带交互效果不需要调用者自己再实现现在的问题就是我该如何实现组件的的交互效果.1. 实现自定义复合组件效果1.1创建复合组件//layout_sub.xml?xml version1.0 encodingutf-8?LinearLayoutxmlns:androidhttp://schemas.android.com/apk/res/androidandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:backgroundcolor/cardview_dark_backgroundButtonandroid:idid/titleBackandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_gravitycenterandroid:layout_margin5dpandroid:textBACK/TextViewandroid:idid/titleTextandroid:layout_width0dpandroid:layout_heightwrap_contentandroid:layout_weight1android:gravitycenterandroid:layout_gravitycenterandroid:textTitle Textandroid:textColorcolor/whiteandroid:textSize24sp/Buttonandroid:idid/titleEditandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_gravitycenterandroid:layout_margin5dpandroid:textEDIT//LinearLayout样式如下所示在主布局中调用//layout_main.xml?xml version1.0 encodingutf-8?LinearLayoutxmlns:androidhttp://schemas.android.com/apk/res/androidandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:fitsSystemWindowstrueincludelayoutlayout/layout_sub//LinearLayout运行看效果1.2 Activity中实现功能//MainActivity.ktclassMainActivity:AppCompatActivity(){overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)findViewByIdButton(R.id.titleBack).setOnClickListener{finish()}findViewByIdButton(R.id.titleEdit).setOnClickListener{Toast.makeText(this,你点击了EDIT按钮,Toast.LENGTH_LONG).show()}}}在调用者的内部通过findViewById()来实现交互逻辑显得实在有些low并且对于复合组件的复用也很不方便因为复合组件的每一个子组件的功能在创建的时候就已经决定了但现在无论谁调用它都需要重复编写交互逻辑重复劳动太多了。事实上上面那个xml文件说是复合组件实际上它连复合组件都不算因为它只是一个将三个View组件放在一起的一个普通xml文件罢了我们引用它的方式也仅仅只是include就像php那样只是占了个位置相当于将它内部的组件给放到了这里。我们可以说它是视觉上的复合组件这是没问题的。但它还绝对算不上说是逻辑交互上的复合组件。1.3 自定义控件实现制定组件的逻辑交互1.3.1 创建控件并绑定自定义组件前言部分我说过自定义控件实际上是一个继承了ViewGroup的layout布局那么是不是说只要我有一个layout布局并将其引入到layout_main.xml中就能实现一样的效果甚至还能拥有自己内置好的交互逻辑答案是肯定的。直接自定义一个类并使其继承LinearLayout类那么这个类就是一个layout布局了。令人疑惑的是这不就是一个继承了LinearLayout布局的类吗为什么他也是一个布局我的回答是不必知道只需要知道继承了LinearLayout布局的类可以作为“代理”来实现复合组件的交互逻辑就行。光有这个类可不行他还没和复合组件建立起任何联系呢。classTitleLayout(context:Context,attrs:AttributeSet):LinearLayout(context){init{LayoutInflater.from(context).inflate(R.layout.layout_sub,this)}}不要看其他地方关注inflate(R.layout.layout_sub,this)这个方法就是将this也就是当前这个类和我创建的复合组件xml文件链接在一起相当于这个类就是这个复合组件了这个类我将其称之为控件类因为它不仅仅是组件了后面还会有逻辑交互能力。这个时候layout_sub才真正成为了一个View一个真正的自定义的复合组件而不仅仅是几个组件的集合。那么这个context是哪里来的呢答案是哪个Activity调用这个控件这个context上下文就属于哪个Activity。LayoutInflater就是用来将xml文件转换成一种View的attrs又是啥呢它是父属性的集合也就是调用这个控件处指定的属性后面会看到的。将上下文传给LinearLayout类这个就不必提了。1.3.2 实现交互逻辑添加代码classTitleLayout(context:Context,attrs:AttributeSet):LinearLayout(context){init{LayoutInflater.from(context).inflate(R.layout.layout_sub,this)findViewByIdButton(R.id.titleBack).setOnClickListener{valactivitycontextasActivity activity.finish()}findViewByIdButton(R.id.titleEdit).setOnClickListener{Toast.makeText(context,你点击了EDIT按钮,Toast.LENGTH_LONG).show()}}}修改引用方式//activity_main.xml?xml version1.0 encodingutf-8?LinearLayoutxmlns:androidhttp://schemas.android.com/apk/res/androidandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:fitsSystemWindowstruecom.bignerdranch.android.recyclerview.TitleLayoutandroid:layout_widthmatch_parentandroid:layout_heightwrap_content//LinearLayout这种引用方式才是View引用而不仅仅是include了2. 进阶ListView2.1 内置布局方式基础使用引入的方式很简单直接使用ListView组件即可和其他的组件比如Button、TextView没什么区别。//activity_main.xml?xml version1.0 encodingutf-8?LinearLayoutxmlns:androidhttp://schemas.android.com/apk/res/androidandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:fitsSystemWindowstrueListViewandroid:idid/listViewandroid:layout_widthmatch_parentandroid:layout_heightmatch_parent//LinearLayout嗯如果只是想展示数据那就在Activity中定义数据集合然后使用ArrayAdapter创建一个适配器val adapter ArrayAdapter String (this, android.R.layout.simple_list_item_1, data)这句使用ArrayAdapter创建了一个适配器将《子项布局方式》和数据放在一起并绑定到this这个Activity中。然后再通过find找到组件并将组件的adapter属性设为上面创建的adapter。classMainActivity:AppCompatActivity(){privatevaldataarrayListOf(abc,dhfi,hdfk,abc,dhfi,hdfk,abc,dhfi,hdfk,abc,dhfi,hdfk,dhfi,hdfk,abc,dhfi,hdfk,abc,dhfi,hdfk)overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)valadapterArrayAdapterString(this,android.R.layout.simple_list_item_1,data)findViewByIdListView(R.id.listView).adapteradapter}}2.2 自定义布局方式这就要用到第一节的知识了自定义复合组件实现更为自由的显示方式不过值得注意的是我们创建的复合组件只是一个子项目item的布局而不是一整个屏幕的布局。代码不写了你到时候看应该能懂我意思总之创建一个图片文字描述的布局xml文件限制图片长宽防止显示不一致文字部分wrap_content即可。关键就在于这个adapter该怎么办最后是要设置ListView的adapter属性的所以需要一个adapter随便写一个类就能作为adapter么那当然不是还是需要继承ArrayAdapter的继承ArrayAdapter之后其实还是不能用的需要重写getView方法为什么因为要自定义布局方式。回看2.1要将item的布局和this结合起来所以我们需要这个getView来生成View也就是将前面提到的xml文件转为View。但我们是要自定义布局方式的系统其实并不知道我们要怎么不写了草这啥b安卓怎么这么难理解滚吧