了解ListView和ViewPager

ListView


定义:

  •     ListView是显示垂直可滚动的列表项视图,列表项的来源可以使用一个适配Adapter,Adapter可将内容从源(如数组或数据库)转换成视图放在列表中。

  •     ListView 控件可使用四种不同视图显示项目。通过此控件,可将项目组成带有或不带有列标头的列,并显示伴随的图标和文本。 可使用 ListView 控件将称作 ListItem 对象的列表条目组织成下列四种不同的视图之一:1.大(标准)图标    2.小图标    3.列表    4.报表   

  •     而View属性决定在列表中控件使用何种视图显示项目。还可用 LabelWrap 属性控制列表中与项目关联的标签是否可换行显示。另外,还可管理列表中项目的排序方法和选定项目的外观。

还是不懂什么是ListView?那就上图(直观点):



  • ListView中一些常用的XML属性:





简单的ListView使用:



  • 一个ListView通常有两个职责。 
  1. 将数据填充到布局。 
  2. 处理用户的选择点击等操作

  • 一个ListView的创建需要3个元素。 
  1. ListView中的每一列的View。 
  2. 填入View的数据或者图片等。 
  3. 连接数据与ListView的适配器。

ListView视图

在Layout布局activity_main里面加入一个ListView

<ListView
    android:id="@+id/list_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</ListView>

在activity活动MainActivity中把这个ListView实例化,以便之后操作。
ListView mlistView = (ListView) findViewById(R.id.list_view);写在onCreate()方法里面就可以了,如下所示

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);     
        ListView mlistView = (ListView) findViewById(R.id.list_view);
    }

效果:


但是这里面空空如也,那是因为我们还没有往里面放item。

Item视图


从最简单开始,我们就做一个只显示一行文字的Item,非常简单,我们只要在layout目录下新建一个xml就可以,在这里我们将它命名为list_item.xml,然后往里面放一个TextView
- 注意:xml中只能放一个TextView,LinearLayout不要

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tv_item"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:padding="20dp"/>

现在我们Item的布局也有了,但是我们现在还存在两个问题 - 1.我们虽说有了Item,但是!Item里面还是没有内容啊! - 2.我们有了ListView布局又有了Item布局,但怎么把它们连在一起呢?

我们一个一个解决,先把内容给写好,所以接下来我们写Data中的数据

Data数据

这里就用一个最简单字符串数组来储存数据
为了简便我们就把它直接写在MainActivity

private String[] data = {
    "item_1",
    "item_2",
    "item_3",
    "item_4",
    "item_5",
    "item_6",
    "item_7"
};

终于我们ListView的布局啊,Item的布局啊,数据啊都写好了!
我们只要把它们给连接起来就好了,但是怎么办呢?
这里我们就要引入一个适配器(Adapter)


Adapter适配器

适配器是一个连接数据和AdapterView(ListView就是一个典型的AdapterView,后面还会学习其他的)的桥梁,通过它能有效地实现数据与AdapterView的分离设置,使AdapterView与数据的绑定更加简便,修改更加方便


其实适配器还有很多,要注意的是,各种Adapter只不过是转换的方式和能力不一样而已。

在这里我们就用一个最简单的ArrayAdapter,因为我们只显示一行字符串
所以将ArrayAdapter的泛型指定为String,也就是ArrayAdapter< String >
不废话了,赶快用代码绑定看看吧,同样也是在MainActivity

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView mlistView = (ListView) findViewById(R.id.list_view);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this,R.layout.list_item,data);
        mlistView.setAdapter(adapter);
    }

注意:我们看到Adapter那行,传了三个参数,分别是上下文Item的布局文件数据

运行结果:


一个非常简单的ListView的运用程序就实现啦!那下面我们就考虑下它的优化:


ListView的优化



  • ListView的优化主要包括两个方面,分别是对自身的优化以及其适配器(Adapter)的优化。 
  • 现在ListView有点落后于时代了,用的比较多的是RecyclerView。(或许以后有空会写一份关于它的博客)
ListView自身的优化 
主要包括一条。对于ListView的layout_height和layout_width设置为match_parent,如果设置为match_parent,一般ListView的宽高会测量三次以上。具体的源码没有深入研究。但为什么会要测量多次,如果对于自定义View稍微有点基础的会知道,对于View的测量大小有三个类型:
  • UNSPECIFIED:未指定的,父类不对子类施加任何限制。
  • EXACTLY:确定的,父类确定其子类控件的大小。
  • AT_MOST:最大值,需要子类去测量自身大小确定。如果我们设置宽高为wrap_content,即AT_MOST,表示其宽高有控件本身去测量确定,而如果是match_parent,则EXACTLY,表示确定的大小。 
Adapter优化。 
对于Adapter的优化,主要包括以下几个步骤: 
  • 复用convertView,减少子布局的生成。 
  • 定义ViewHolder,减少findViewById()的次数。


ListView参考资料:https://blog.csdn.net/pibalibala/article/details/44515225


ViewPager


定义:

ViewPager是Android开发者比较常用的一个控件了,由于它允许数据页从左到右或者从右到左翻页,因此这种交互也备受设计师的青睐。在APP中的很多场景都用得到,比如第一次安装APP时的用户引导页、图片浏览时左右翻页、广告Banner页等等都会用到ViewPager

直观点,上图:

1.ViewPager的简介和作用
ViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的view
1)ViewPager类直接继承了ViewGroup类,所有它是一个容器类,可以在其中添加其他的view类。
2)ViewPager类需要一个PagerAdapter适配器类给它提供数据。
3)ViewPager经常和Fragment一起使用,并且提供了专门的FragmentPagerAdapter和FragmentStatePagerAdapter类供Fragment中的ViewPager使用。

2.ViewPager的适配器
简介中提到了PagerAdapter,和ListView等控件使用一样,需要ViewPager设置PagerAdapter来完成页面和数据的绑定,这个PagerAdapter是一个基类适配器,我们经常用它来实现app引导图,它的子类有FragmentPagerAdapter和FragmentStatePagerAdapter,这两个子类适配器用于和Fragment一起使用,在安卓应用中它们就像listview一样出现的频繁。

实现一个最基本的PagerAdapter, 《必须实现四个方法》 ,在代码里有注释
public class AdapterViewpager extends PagerAdapter { 
private List<View> mViewList; 

public AdapterViewpager(List<View> mViewList) {
 this.mViewList = mViewList; 
} 

@Override public int getCount() {//必须实现 
return mViewList.size(); 
} 

@Override public boolean isViewFromObject(View view, Object object) {//必须实现 
return view == object; 
} 

@Override public Object instantiateItem(ViewGroup container, int position) {//必须实现,实例化 
container.addView(mViewList.get(position));
 return mViewList.get(position);
 } 

@Override public void destroyItem(ViewGroup container, int position, Object object) {//必须实现,销毁 
container.removeView(mViewList.get(position));
 } 

}
//链接:https://www.jianshu.com/p/e5abbda4a71c



简单的ViewPager使用:



1. xml引用

<android.support.v4.view.ViewPager
    android:id="@+id/vp"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</android.support.v4.view.ViewPager>

2. page布局

<?xml version="1.0" encoding="utf-8"?>
<TextView
    android:id="@+id/tv"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FAE8DA"
    android:gravity="center"
    android:text="Hello"
    android:textSize="22sp">
</TextView>

3. 创建适配器

可直接创建PagerAdapter,亦可创建它的子类

public class MyPagerAdapter extends PagerAdapter {
    private Context mContext;
    private List<String> mData;

    public MyPagerAdapter(Context context ,List<String> list) {
        mContext = context;
        mData = list;
    }

    @Override
    public int getCount() {
        return mData.size();
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View view = View.inflate(mContext, R.layout.item_base,null);
        TextView tv = (TextView) view.findViewById(R.id.tv);
        tv.setText(mData.get(position));
        container.addView(view);
        return view;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        // super.destroyItem(container,position,object); 这一句要删除,否则报错
        container.removeView((View)object);
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }
}

4. 设置适配器

private void setVp() {
    List<String> list = new ArrayList<>();
    for (int i = 0; i < 3; i++) {
       list.add("第"+i+"个View");
    }

    ViewPager vp = (ViewPager) findViewById(R.id.vp);
    vp.setAdapter(new MyPagerAdapter(this,list));
}

效果:




与Fragment结合使用

这种方法最好用于有限个静态fragment页面的管理。尽管不可见的视图有时会被销毁,但用户所有访问过的fragment都会被保存在内存中。因此fragment实例会保存大量的各种状态,这就造成了很大的内存开销。

与Fragment结合使用其实也一样,只是用Fragment代替原先的View,填充Viewpager;然后就是Adapter不一样,配合Fragment使用的有两个Adapter:FragmentPagerAdapterFragmentStatePagerAdapter

相同点:
FragmentPagerAdapter和FragmentStatePagerAdapter都继承自PagerAdapter

不同点:
卸载不再需fragment时,各自采用的处理方法有所不同

FragmentStatePagerAdapter会销毁不需要的fragment。事务提交后, activity的FragmentManager中的fragment会被彻底移除。 FragmentStatePagerAdapter类名中的“state”表明:在销毁fragment时,可在onSaveInstanceState(Bundle)方法中保存fragment的Bundle信息。用户切换回来时,保存的实例状态可用来恢复生成新的fragment

FragmentPagerAdapter有不同的做法。对于不再需要的fragment, FragmentPagerAdapter会选择调用事务的detach(Fragment)方法来处理它,而非remove(Fragment)方法。也就是说, FragmentPagerAdapter只是销毁了fragment的视图, fragment实例还保留在FragmentManager中。因此,FragmentPagerAdapter创建的fragment永远不会被销毁

也就是:在destroyItem()方法中,FragmentStatePagerAdapter调用的是remove()方法,适用于页面较多的情况;FragmentPagerAdapter调用的是detach()方法,适用于页面较少的情况。但是有页面数据需要刷新的情况,不管是页面少还是多,还是要用FragmentStatePagerAdapter,否则页面会因为没有重建得不到刷新


ViewPage参考:

https://blog.csdn.net/weixin_39251617/article/details/79399592

https://www.jianshu.com/p/e5abbda4a71c


基于ViewPager实现广告轮播控件    //此项技能还是挺有用的
https://github.com/daimajia/AndroidImageSlider    //转载






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值