美文网首页
【基础笔记】ListView、GridView、Recycler

【基础笔记】ListView、GridView、Recycler

作者: 究极无敌棒棒糖 | 来源:发表于2019-11-19 22:48 被阅读0次

ListView

一、什么是ListView,为什么要使用ListView?

ListView可以一列一列的显示图标和文本。(类似QQ聊天和翻阅微博消息)
ListView允许用户通过手指上下滑动的方式将屏幕外的数据滚动到屏幕内,同时屏幕上原有的数据则会滚动出屏幕。

二、ListView的使用

1、创建实体类(model、entity、bean)

public class Fruit {
    private String name;
    private int imageId;

    public Fruit(String name, int imageId) {
        this.name = name;
        this.imageId = imageId;
    }

    public String getName() {
        return name;
    }

    public int getImageId() {
        return imageId;
    }

2、xml布局

  • Item布局(根据实体类的部分或全部需要显示的属性布局)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="测试" />

</LinearLayout>
  • Activity布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ListViewActivity">
    
    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />


</LinearLayout>

3、Adapter

public class FruitAdapter extends BaseAdapter {
    private List<Fruit> mFruits;//列表数据源
    private Context mContext;//需要传入的Context

    FruitAdapter(Context context) {
        mContext = context;
    }

    //新增数据
    public void initData(List<Fruit> fruits) {
        if (mFruits == null){
            mFruits = new ArrayList<>();
        }
        if (fruits == null) {
            return;
        }
        mFruits.addAll(fruits);
        notifyDataSetChanged();//记得刷新控件
    }

    @Override
    public int getCount() {
        return mFruits == null ? 0 : mFruits.size();
    }

    @Override
    public Fruit getItem(int i) {
        return mFruits.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    /**
     * @param position    选择的第几个Item的位置
     * @param convertView 展示在界面上的一个item
     * @param parent      装载convertView的父视图
     * @return 当前的Item
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Fruit fruit = getItem(position);
        ViewHolder viewHolder;
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item, null);//固定写法
            viewHolder = new ViewHolder(convertView);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        viewHolder.fruitName.setText(fruit.getName());
        viewHolder.fruitImage.setImageResource(fruit.getImageId());
        return convertView;
    }

    class ViewHolder {
        ImageView fruitImage;
        TextView fruitName;

        private ViewHolder(View view) {
            fruitImage = view.findViewById(R.id.iv);
            fruitName = view.findViewById(R.id.tv);
        }
    }

}

添加数据之后记得刷新adapter

4、Activity

public class ListViewActivity extends AppCompatActivity {

    private List<Fruit> fruitList = new ArrayList<>();//初始化数据源

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list_view);
        ListView listView = findViewById(R.id.list_view);
        //添加数据
        init();
        //生成适配器(Item已经在Adapter中绑定好了,只需入当前Context)并传入数据
        FruitAdapter adapter = new FruitAdapter(this);
        adapter.initData(fruitList);
        //ListView绑定适配器
        listView.setAdapter(adapter);
    }

    /**
     * 初始化,添加数据
     */
    private void init() {
        for (int i = 0; i < 2; i++) {
            Fruit apple = new Fruit("Apple", R.drawable.ic_launcher_background);
            fruitList.add(apple);
            Fruit banana = new Fruit("Banana", R.drawable.ic_launcher_background);
            fruitList.add(banana);
            Fruit orange = new Fruit("Orange", R.drawable.ic_launcher_background);
            fruitList.add(orange);
            Fruit watermelon = new Fruit("Watermelon", R.drawable.ic_launcher_background);
            fruitList.add(watermelon);
            Fruit pear = new Fruit("Pear", R.drawable.ic_launcher_background);
            fruitList.add(pear);
            Fruit grape = new Fruit("Grape", R.drawable.ic_launcher_background);
            fruitList.add(grape);
            Fruit pineapple = new Fruit("Pineapple", R.drawable.ic_launcher_background);
            fruitList.add(pineapple);
            Fruit strawberry = new Fruit("Strawberry", R.drawable.ic_launcher_background);
            fruitList.add(strawberry);
            Fruit cherry = new Fruit("Cherry", R.drawable.ic_launcher_background);
            fruitList.add(cherry);
            Fruit mango = new Fruit("Mango", R.drawable.ic_launcher_background);
            fruitList.add(mango);
        }
    }

}

总结:①. 先根据数据类Entity型确定Item,然后对Item和Activity进行Xml布局。
②. Adapter继承于BaseAdapter(Adapter中要传入ContextEntity数据源,Item布局的Id),先初始化ContextEntity数据源。在构造器中传入Context;写一个initData()的方法,将数据传入Adapter;在重写BaseAdapter的四个方法的getView()方法中绑定Item的各个视图,对视图进行相关操作。ViewHolder当然也是不可少的
③. 在Activity中先new Adapter(this)传入当前的contextEntity数据通过adapter.initData()将数据传入Adapter中,Adapter通过ListView.setAdapter(adapter)将适配器和ListView绑定起来。
处理好的数据要传入Adapter,通过adapter的getView()才能显示出来

三、ListView的常用属性

  • android:divider="@null":除掉分隔线。也可以用该属性为分隔线添加不同颜色,图片。

  • android:dividerHeight:设置分割线的高度

  • android:footerDividersEnabled="false",headerDividersEnabled="false":除掉顶部、底部分隔线。

  • android:scrollbars="none":除掉滚动条

  • android: fadingEdge="none":除掉上下边的阴影

  • android: cacheColorHint:拖动时的背景颜色

  • android: listSelector:Item点击时的背景。

  • android: transcriptMode="alwaysScroll":出现新条目时,自动滚动到可见的新条目处。

  • android: choiceMode:子item的选择模式。

~这样看似复杂,其实和实际工作比起来复杂程度还是差了一点。但是工作的基本思路也是这样的,可以按照这样的思维写下去
~对了,ListView可以对整个Item设置点击事件,和Button的点击操作类似,有兴趣可以自己试一试
~Item布局和Adapter可以用Android Studio自带的simple_list_item_1和ArrayAdapter<>,使用起来更加简单


GridView

一、什么是GridView,它和ListView的区别?

GridView(网格视图)是按照行列的方式来显示内容的,一般用于显示图片,图片文字等内容,比如实现十六宫格,九宫格,四宫格等,用GridView是首选,也是最简单的。
GridViewListView的主要区别在于ListView不能直接进行网格布局,而GridView可以

二、GridView的使用

1、创建实体类(model、entity、bean) 同上

2、xml布局

  • Item布局 同上
  • Activity布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">


    <GridView
        android:id="@+id/grid_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:columnWidth="90dp"
        android:numColumns="3"
        android:stretchMode="columnWidth"
        android:verticalSpacing="10dp" />


</LinearLayout>

3、Adapter(同上)

4、Activity(同上,只需要将ListView替换为GridView就可以了)

总结:与ListView的使用方法几乎一毛一样,网格布局的时候就用GridView

三、GridView的属性

  • android:columnWidth:设置列的宽度
  • android:gravity:组件对其方式
  • android:horizontalSpacing:水平方向每个单元格的间距
  • android:verticalSpacing:垂直方向每个单元格的间距
  • android:numColumns:设置列数
  • android:stretchMode:设置拉伸模式,可选值如下: none:不拉伸;spacingWidth:拉伸元素间的间隔空隙 columnWidth:仅仅拉伸表格元素自身 spacingWidthUniform:既拉元素间距又拉伸他们之间的间隔空袭

RecyclerView

一、什么是RecyclerView,它和ListView的区别?

RecyclerView可以说是一个增强版的ListView,不仅可以轻松实现和ListView同样的效果,还优化了ListView中存在的各种不足之处。

二、RecyclerView的使用

1、添加依赖

implementation 'com.android.support:recyclerview-v7:27.1.1' //RecyclerView
2、创建实体类(model、entity、bean)
package com.example.administrator.recyclerview;

public class Fruit {
    private String name;
    private int imageId;

    public Fruit(String name, int imageId) {
        this.name = name;
        this.imageId = imageId;
    }

    public String getName() {
        return name;
    }

    public int getImageId() {
        return imageId;
    }
}

3、xml布局

  • Item布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:orientation="horizontal"
    android:gravity="center"
    android:layout_height="wrap_content">


    <ImageView
        android:id="@+id/iv_fruit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_launcher_background" />

    <TextView
        android:id="@+id/tv_fruit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="水果" />
</LinearLayout>
  • Activity布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

4、Adapter(重点)

package com.example.administrator.recyclerview;

import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
    private List<Fruit> mFruitList;

    public FruitAdapter (){

    }

    //添加数据,必要时候刷新
    public void addData(List<Fruit> data){
        if (mFruitList == null){
            mFruitList = new ArrayList<>();
        }
        if (data != null){
          int startSize = mFruitList.size();
          mFruitList.addAll(data);
          int endSize = mFruitList.size();
          notifyItemRangeChanged(startSize, endSize - startSize);//范围刷新新添加的数据
        }
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //绑定Item
        View inflate = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler, parent, false);
        ViewHolder viewHolder = new ViewHolder(inflate);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        //给Item的布局控件赋值
        holder.textView.setText(mFruitList.get(position).getName());
        holder.imageView.setImageResource(mFruitList.get(position).getImageId());
    }

    @Override
    public int getItemCount() {
        return mFruitList == null ? 0 : mFruitList.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder{
        TextView textView;
        ImageView imageView;
        ViewHolder(View view) {
            super(view);
            textView = view.findViewById(R.id.tv_fruit);
            imageView = view.findViewById(R.id.iv_fruit);
        }
    }
}

RecyclerView拥有多种Item的刷新方式:

  • notifyDataSetChanged();//数据源改变后刷新整个列表
  • notifyDataSetChanged();//刷新整个列表
  • notifyItemRangeChanged(startSize, endSize - startSize);//范围刷新新添加的数据
  • notifyItemChanged();//指定刷新某个位置的Item
  • notifyItemMoved();//移动Item
    等等等等

5、Activity

package com.example.administrator.recyclerview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private FruitAdapter adapter;
    private List<Fruit> fruitList = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = findViewById(R.id.recycler_view);
        //准备数据
        adapter = new FruitAdapter();
        initData();
        adapter.addData(fruitList);
        //RecyclerView布局
        LinearLayoutManager manager = new LinearLayoutManager(this);
        manager.setOrientation(LinearLayoutManager.HORIZONTAL);
//        GridLayoutManager manager = new GridLayoutManager(this,3);   网格布局
//        StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);  瀑布布局
        recyclerView.setLayoutManager(manager);
        recyclerView.setAdapter(adapter);
    }

      private void initData() {
        Fruit apple = new Fruit("Apple", R.drawable.ic_launcher_background);
        fruitList.add(apple);
        Fruit banana = new Fruit("Banana", R.drawable.ic_launcher_background);
        fruitList.add(banana);
        Fruit orange = new Fruit("Orange", R.drawable.ic_launcher_background);
        fruitList.add(orange);
        Fruit watermelon = new Fruit("Watermelon", R.drawable.ic_launcher_background);
        fruitList.add(watermelon);
        Fruit pear = new Fruit("Pear", R.drawable.ic_launcher_background);
        fruitList.add(pear);
        Fruit grape = new Fruit("Grape", R.drawable.ic_launcher_background);
        fruitList.add(grape);
        Fruit pineapple = new Fruit("Pineapple", R.drawable.ic_launcher_background);
        fruitList.add(pineapple);
        Fruit strawberry = new Fruit("Strawberry", R.drawable.ic_launcher_background);
        fruitList.add(strawberry);
        Fruit cherry = new Fruit("Cherry", R.drawable.ic_launcher_background);
        fruitList.add(cherry);
        Fruit mango = new Fruit("Mango", R.drawable.ic_launcher_background);
        fruitList.add(mango);

    }
}

三、RecyclerView的常用方法

  • addItemDecoration();//添加Item的样式
  • computeVerticalScrollRange();//获取Recycler内容高度
  • getAdapter().getItemCount();//获得Adapter中Item总个数
  • getChildCout();//获取RecyclerView可见Item个数
  • smoothScrollToPosition(0);//将某个位置的Item滑动到顶部(有滚动效果,平滑动画,适用于列表数量不多的情况)
  • scrollToPositionWithOffset(0,0);//将某个位置的Item滑动到顶部(无动画,不平滑)

四、给整个Item设置点击事件(待补充)

因为RecyclerView没有对整个Item设置点击事件的方法,要想对整个Item设置点击事件需要在Adapter里面写一个回调方法。(之后补充)

五、给Item设置分割和点击样式(待补充)


ScrollView

一、什么是ScrollView

视图的滚动过程,其实是在不断修改原点坐标。当手指触摸后,ScrollView会暂时拦截触摸事件,使用一个计时器。假如在计时器到点后没有发生手指移动事件,那么ScrollView发送tracking events到被点击的subView;若是在计时器到点后发生了移动事件,那么ScrollView取消tracking自己促发滚动。

二、ScrollView的用法

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".ListViewActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="vertical">

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

    </LinearLayout>

</ScrollView>
  • HorizontalScrollView:水平滑动。只需将ScrollView替换为HorizontalScrollView,LinearLayout的方向改变为vertical。
  • 注意:ScrollView的子元素只能有一个,所以得增加一个LinearLayout布局,把其他控件放在这个LinearLayout中,那么ScrollViewd的子元素就只有一个LinearLayout了,而LinearLayout的子元素不限制。

三、ScrollView的属性

  • android:scrollbars:设置滚动条显示。none(隐藏),horizontal(水平),vertical(垂直)。
  • android:scrollbarFadeDuration:设置滚动条淡出效果(从有到慢慢的变淡直至消失)时间,以毫秒为单位。Android2.2中滚动条滚动完之后会消失,再滚动又会出来,在1.5、1.6版本里面会一直显示着。
  • android:scrollbarSize:设置滚动条的宽度。
  • android:scrollbarStyle:设置滚动条的风格和位置。设置值:insideOverlay、insideInset、outsideOverlay、outsideInset
  • android:scrollbarThumbHorizontal:设置水平滚动条的drawable。
  • android:scrollbarThumbVertical:设置垂直滚动条的drawable.
  • android:scrollbarTrackHorizontal:设置水平滚动条背景(轨迹)的色drawable
  • android:soundEffectsEnabled:设置点击或触摸时是否有声音效果

四、ScrollView嵌套ListView的滑动冲突

滑动冲突
  • 当ListView放入ScrollView后,ListView的数据就只能显示一行,严重影响使用体验。
  • 原因是scrollView中的ListView在计算高度时跳过了measureHeightOfChildren方法的,只计算了第一个item的高度,因而只会显示一条数据的高度。
  • 解决办法:自定义一个ExpandingListView 继承Listview,然后重写onMeasure方法。
public class ExpandingListView  extends ListView {

    public ExpandingListView(Context context) {
        super(context);  
    }

    public ExpandingListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);  
    }

    public ExpandingListView(Context context, AttributeSet attrs) {
        super(context, attrs);  
    }

     //重写OnMeasure方法
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }

}

注意:GridView的滑动冲突同理

五、ScrollView嵌套RecyclerView的滑动冲突

recyclerView.setLayoutManager(new LinearLayoutManager(this){
  @Override
  public boolean canScrollVertically() {
  //解决ScrollView里存在多个RecyclerView时滑动卡顿的问题
  //如果你的RecyclerView是水平滑动的话可以重写canScrollHorizontally方法
    return false;
  }
  });
//解决数据加载不完的问题
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(true);
//解决数据加载完成后, 没有停留在顶部的问题
recyclerView.setFocusable(false);

使用了上面的方法还无法解决就把布局中的RecyclerView外层的ScrollView换成NestedScrollView就可以解决了

六、ScrollView嵌套EditView、TextView的滑动冲突

1、Activity中设置共同的滑动监听

private OnTouchListener touchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
  if(event.getAction() == MotionEvent.ACTION_DOWN
    || event.getAction() == MotionEvent.ACTION_MOVE){
   //按下或滑动时请求父节点不拦截子节点
  v.getParent().requestDisallowInterceptTouchEvent(true);
  }
  if(event.getAction() == MotionEvent.ACTION_UP){
    //抬起时请求父节点拦截子节点
    v.getParent().requestDisallowInterceptTouchEvent(false);
  }
   return false;
  }
};

2、EditText和TextView对象调用该事件

editText.setOnTouchListener(touchListener);
textView.setOnTouchListener(touchListener);
//textView单独设置滑动方法
textView.setMovementMethod(ScrollingMovementMethod.getInstance());

3、XML滑动条设置

android:scrollbars="vertical"
android:scrollbarStyle="outsideOverlay"

相关文章

网友评论

      本文标题:【基础笔记】ListView、GridView、Recycler

      本文链接:https://www.haomeiwen.com/subject/niunbctx.html