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中要传入Context
,Entity
数据源,Item布局
的Id),先初始化Context
和Entity
数据源。在构造器中传入Context
;写一个initData()
的方法,将数据传入Adapter;在重写BaseAdapter的四个方法的getView()
方法中绑定Item的各个视图,对视图进行相关操作。ViewHolder
当然也是不可少的
③. 在Activity中先new Adapter(this)传入当前的context
,Entity
数据通过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是首选,也是最简单的。
GridView
和ListView
的主要区别在于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"
网友评论