您的位置:首页 > 移动开发 > Android开发

Android基础控件ListView的使用与焦点冲突解决

2017-03-31 14:52 513 查看

ListView的使用与焦点冲突

ListView的基础使用:(项目地址

ListView是一个列表视图,对于要反复显示多条切不确定数量的时候并且视图效果基本一致但是每一条数据皆不同的的时候显然在布局文件中一个个控件去写就会显得非常的不明智并且效率低下,因此谷歌就推出这个基础控件ListView并封装了一些基本显示的效果提供给开发者使用,首先看看我写好的代码一个是使用谷歌自带封装好的显示方式(也就是适配器Adapter)另外两个则是我自己封装好的适配器可以鉴于我自己封装好的代码思路在一定的开发环境中使用大大减少代码的冗余性提高代码的简洁性。

ListView为什么要使用适配器呢?适配器(Adapter)的作用是为了对于每一项数据他显示什么样要做到什么显示效果列如我快上线的一个项目(桂林电子科技大学北海校区水电维修App)中一个布局要显示一个列表而列表的效果是做一个时光轴的效果如图



这样一个视图效果也都是由适配器去控制显示现在就展示部分代码其余代码截图显示如果需要封装好的项目某些源码请下载浏览链接地址

MainActivity

public class MainActivity extendsAppCompatActivity  {

   private ListView listView;

   private List<ItemDemo1> list;

   private List<ItemDemo2> list2;

   private String[] arr = new String[10];

   @Override

   protected void onCreate(Bundle savedInstanceState) {

       super.onCreate(savedInstanceState);

       setContentView(R.layout.activity_main);

       list = new ArrayList<>();

       list2 = new ArrayList<>();

       for (int i = 0; i <= 9; i++) {

           arr[i] = "第" + i + 1 + "项";

           list.add(new ItemDemo1("第" + i + 1 +"项",
R.mipmap.ic_launcher));

           list2.add(new ItemDemo2(false));

       }

       listView = (ListView) findViewById(R.id.listview);

/**这里使用了系统默认封装好的布局方式*/

       listView.setAdapter(new ArrayAdapter<>(MainActivity.this,android.R.layout.simple_list_item_1, arr));}

/**下面分别调用显示我封装好的视频器注意适配器使用了简单的架构模式来编写使得适配器有更好的拓展性*/

   public void onclick(View view) {

       switch (view.getId()) {

           case R.id.btn1:

                ShowMessage.showMessage(this,"DIYdemo1显示");

                listView.setAdapter(newDemoAdapter1(this, list));

                break;

           case R.id.btn2:

                ShowMessage.showMessage(this,"DIYdemo2显示");

                listView.setAdapter(newDemoAdapter2(this, list2));

               listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                    @Override

                    public voidonItemClick(AdapterView<?> parent, View view, int position, long id) {

                       ShowMessage.showMessage(MainActivity.this,"我是第几项"+(position+1));

                    }});

                break;}}}



那么使用自己手写的适配器与谷歌自带的简单适配器有什么好处呢?好处一可以自定义更多美观性的布局显示方式如刚刚展示时光轴这样一个效果。好处二可以更加贴合实际开发需求所需效果,好处三:高手使用它的时候都会做到初学者没做到一件东西就是布局复用,为什么要使用布局效果?因为每一个加载的view都是一层视图过多的视图在某一刻导致APP运行可能奔溃也就是(OOM内存溢出这样一个异常)列如:比较古老的三方Xlistview就是对ListView进行一个上拉加载下拉显示数据的一个封装效果但其里面也带有布局复用效果。

使用布局复用效果也就是对返回的View就行一个Tag标记这样子然后取出Tag这样一个作用。通过设置取出Tag这样的编码操作大大的减少了每一个Item视图的创建步骤避免了视图加载异常的操作,如图:



我对一个内部类GetView声明并在预处理的情况下进行对象创建并将它作为一个Tag标记到取出的Tag的一个方法就可以进行对View层的复用这样减少了内存的过多的对象堆存保证内存中对象轻便性上性能优化。

来我们先看程序运行的效果和日志输出:



Log日志输出:

03-31 05:37:17.3063214-3214/ypz.com.listviewdemo I/易庞宙: DIYdemo1显示

03-31 05:37:41.9213214-3214/ypz.com.listviewdemo I/易庞宙: DIYdemo2显示

效果分析:当我分别点击这两个按钮的时候分别适配显示了我封装不同的适配器并显示其结果。

使用心得:如果项目中拥有不同的ListView显示
be0d
效果但是每次编写代码适配器过于麻烦的时候建议使用我封装的一种思路可以减少代码的编写,如我创建一个空类里面毫无成员变量,而又创建一个适配器基类,进行传参构造方法的是时候可以这样子写:



然后让其余适配器继承这个适配器基类只需要写本类中的适配器构造方法并重写getView方法即可这样大大减少一些没必要方法的重写,通过这样的效果达到了减少代码冗余性,并提高有效代码的使用比,更保证这编译过程中速度加载的优越性,这也是一种框架思维,能减少冗余性并提高代码的拓展性可阅性,很多人会问我为什么适配器基类中会有List集合里面为什么会有一个空类这是为了让以后使用list集合中传入进行构造传参并赋予基类中的时候,通过泛型继承的一个思维去拓展使用增加基类的拓展性以及高效性。

焦点冲突的解决方案:

一般情况下有三种:
第一种:在Item布局对于一些Button或者CheckBox之类会抢占焦点的时候设置将ListView中的Item布局中的子控件focusable属性设置为false
第二种:在getView方法中将抢占焦点的控件调用setFocusable(false)
第三种:设置item的根布局的属性android:descendantFocusability="blocksDescendant"我们可以发现,其实这三种方法都是为了让Button等控件不能获取焦点,从而使得item可以响应点击事件。
第三种方法使用起来相对方便,因为它是将item布局中的其他所有控件都设置为不能获取焦点。将ListView中的Item布局中的子控件focusable属性设置为false
我们可以发现,其实这三种方法都是为了让Button等控件不能获取焦点,从而使得item可以响应点击事件。
第三种方法使用起来相对方便,因为它是将item布局中的其他所有控件都设置为不能获取焦点。
android:descendantFocusability属性共有三个取值,分别为
beforeDescendants:viewgroup会优先其子类控件而获取到焦点

afterDescendants:viewgroup 只有当其子类控件不需要获取焦点时才获取焦点

blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐