这篇文章我们将重点介绍ListView控件,并介绍 适配器(Adapter) 的使用,适配器的作用是将复杂的数据填充在指定的视图界面上
,这么说可能不太明白,下面我们会详细介绍,本篇介绍的控件包括:
ListView 以列表的形式展示数据,需要用到 适配器 搭建数据源和视图界面的桥梁
。如果是单一的数据,可使用ArrayAdapter适配器加载数据。我们需要把数据加载到适配器中,再将适配器绑定给ListView,具体步骤如下:
实例:
activity_main.xml
<?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"
android:orientation="vertical"
tools:context=".MainActivity">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#00000000"></ListView>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
private ListView listView;
private ArrayAdapter<String> adapter;//适配器
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listView);
String data[] ={"apple","banana","watermelon","pear","peach"};//数据源
adapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,data);//适配器绑定数据源
listView.setAdapter(adapter);//ListView绑定适配器
}
}
ArrayAdapter<>(this,android.R.layout.simple_list_item_1,data); 3个参数分别是:
效果:
是不是挺简单的,这里提出一个问题:怎么让ListView中的每一项具有点击事件呢? 这里依旧用到我们上篇文章介绍Button时学到的 监听器,ListView的监听器是 OnItemClickListener ,监听器中的 int类型参数 position 表示点击项为第几项(从0数起)。
MainActivity.java
//监听器
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String text = listView.getItemAtPosition(position)+"";//getItemAtPosition()方法用于获取被点击项的内容
Toast.makeText(MainActivity.this, position +" , "+ text,Toast.LENGTH_SHORT).show();
}
});
效果:
上面的实例中,列表项是单一的数据,如果我们要实现每个列表项由 图片+文字内容 组成呢?能不能做到呢?答案是肯定的,这里我们只需要自定义我们的列表项布局,自定义适配器即可,步骤如下:
实例如下:
item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:id="@+id/imageView"
android:src="@mipmap/ic_launcher"
android:layout_width="100dp"
android:layout_height="100dp" />
<TextView
android:id="@+id/textView2"
android:text="fruit"
android:textSize="40dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Fruit.java
public class Fruit {
private String name;
private int imageid;
public Fruit(int imageid, String name){
this.name = name;
this.imageid = imageid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getImageid() {
return imageid;
}
public void setImageid(int imageid) {
this.imageid = imageid;
}
}
FruitAdapter .java
public class FruitAdapter extends ArrayAdapter<Fruit> {
private int itemLayout;
public FruitAdapter(Context context, int resource, List<Fruit> objects) {
super(context, resource, objects);
itemLayout = resource;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//1.获取列表项的实例
Fruit fruit = getItem(position);
//2.设置列表项的布局
View view = LayoutInflater.from(getContext()).inflate(itemLayout,null);
//3.绑定控件实例
ImageView imageView = view.findViewById(R.id.imageView);
TextView textView = view.findViewById(R.id.textView2);
imageView.setImageResource(fruit.getImageid());
textView.setText(fruit.getName());
return view;
}
}
public class Main2Activity extends AppCompatActivity {
private ListView listView;
private FruitAdapter fruitAdapter;
private List<Fruit> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
listView = findViewById(R.id.listView2);
//1.数据源
list = new ArrayList<>();//创建list实例
listinit();
//2.适配器绑定数据源
fruitAdapter = new FruitAdapter(Main2Activity.this,R.layout.item,list);
//3.ListView绑定适配器
listView.setAdapter(fruitAdapter);
}
private void listinit() {
int image[] = {R.drawable.apple,R.drawable.banana,R.drawable.watermelon,R.drawable.pear,R.drawable.peach};
String data[] ={"apple","banana","watermelon","pear","peach"};
for (int i=0;i<5;i++){
Fruit fruit = new Fruit(image[i],data[i]);
list.add(fruit);
}
}
}
效果:
这样一来我们就实现了复杂的列表项,看似完美其实还是有地方可以优化的。FruitAdapter.java的getView()会在每获取一个列表项时就执行一次,而我们在该方法中执行了一下代码:
//设置列表项的布局
View view = LayoutInflater.from(getContext()).inflate(itemLayout,null);
//绑定控件实例
ImageView imageView = view.findViewById(R.id.imageView);
TextView textView = view.findViewById(R.id.textView2);
这就意味着我们每获取一个列表项都需要重新加载一遍布局,这种做法相当低效。因此,我们把显示过的item View缓存起来,下次使用时直接复用就能提高LIstView的运行效率了,优化后的代码如下:
FruitAdapter.java
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//1.获取列表项的实例
Fruit fruit = getItem(position);
View view;
ViewHolder viewHolder;
if (convertView == null){
//2.设置列表项的布局
view = LayoutInflater.from(getContext()).inflate(itemLayout,null);
//3.绑定控件实例
viewHolder = new ViewHolder();
viewHolder.imageView = view.findViewById(R.id.imageView);
viewHolder.textView = view.findViewById(R.id.textView2);
view.setTag(viewHolder);
}else {
view = convertView;
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.imageView.setImageResource(fruit.getImageid());
viewHolder.textView.setText(fruit.getName());
return view;
}
class ViewHolder{
ImageView imageView;
TextView textView;
}
Spinner是下拉列表,使用类似于ListView,监听器为 OnItemSelectedListener ,使用步骤如下:
实例:
activity_spinner.xml
<?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"
android:orientation="vertical"
tools:context=".SpinnerActivity">
<TextView
android:id="@+id/textView3"
android:text="今天打算吃什么水果?"
android:textSize="30dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Spinner
android:id="@+id/spinner"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"></Spinner>
</LinearLayout>
SpinnerActivity.java
public class SpinnerActivity extends AppCompatActivity {
private TextView textView;
private Spinner spinner;
private List<String> fruitList;
private ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_spinner);
textView = findViewById(R.id.textView3);
spinner = findViewById(R.id.spinner);
//1.数据源
fruitList = new ArrayList<>();
init();
//2.适配器
adapter = new ArrayAdapter<>(this,android.R.layout.simple_spinner_item,fruitList);
//选择下拉列表样式
adapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
//3.Spinner绑定适配器
spinner.setAdapter(adapter);
//4.Spinner添加监听器
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String fruitName = adapter.getItem(position);
textView.setText("今天打算吃"+ fruitName);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
private void init() {
String data[] ={"apple","banana","watermelon","pear","peach"};
for (int i=0;i<5;i++){
fruitList.add(data[i]);
}
}
}
GridView是网格视图,属于网格版的ListVIew,监听器跟LIstView一样使用的是 OnItemClickListener,先来了解一下GridView特有的属性吧:
我们这里使用另一种适配器 SimpleAdapter 来写一个简单的例子,步骤基本跟ListView一样,这里主要学习一下SimpleAdapter 的使用方法,具体步骤如下:
实例:
<GridView
android:id="@+id/gridView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:horizontalSpacing="20dp"
android:verticalSpacing="20dp"
android:layout_marginTop="20dp"
android:numColumns="2"></GridView>
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_grid_view);
gridView = findViewById(R.id.gridView);
//2.准备数据源
fruitList = new ArrayList<>();
listinit();
}
private void listinit() {
int image[] = {R.drawable.apple,R.drawable.banana,R.drawable.watermelon,R.drawable.pear,R.drawable.peach};
String data[] ={"apple","banana","watermelon","pear","peach"};
for (int i=0;i<data.length;i++){
Map<String,Object> map = new HashMap<>();
map.put("image",image[i]);
map.put("data",data[i]);
fruitList.add(map);
}
}
//3.适配器绑定数据源
simpleAdapter = new SimpleAdapter(GridViewActivity.this,fruitList,R.layout.item2,new String[]{"image","data"},new int[]{R.id.imageView2,R.id.textView3});
//4.GridView绑定适配器
gridView.setAdapter(simpleAdapter);
//5.给GridView添加监听器
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(GridViewActivity.this,position+":"+ data[position],Toast.LENGTH_SHORT).show();
}
});
ViewPager是视图滑动切换工具,是如今应用相当广泛的一个控件,ViewPager的 监听器 是 OnPageChangeListener。这里通过一个简单实例来介绍如何使用ViewPager,和介绍一个新的 适配器 PagerAdapter,具体步骤如下:
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.PagerTabStrip
android:id="@+id/pagerTabStrip"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v4.view.PagerTabStrip>
</android.support.v4.view.ViewPager>
public class ViewPagerActivity extends AppCompatActivity {
private ViewPager viewPager;
private PagerTabStrip pagerTabStrip;
private List<View> viewList;
private List<String> titleList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_pager);
viewPager = findViewById(R.id.viewPager);
pagerTabStrip = findViewById(R.id.pagerTabStrip);
viewList = new ArrayList<>();
titleList = new ArrayList<>();
//2.准备数据源(需要手动创建4个简单的布局文件)
View view1 = View.inflate(this,R.layout.page1,null);
View view2 = View.inflate(this,R.layout.page2,null);
View view3 = View.inflate(this,R.layout.page3,null);
View view4 = View.inflate(this,R.layout.page4,null);
viewList.add(view1);
viewList.add(view2);
viewList.add(view3);
viewList.add(view4);
titleList.add("第一页");
titleList.add("第二页");
titleList.add("第三页");
titleList.add("第四页");
}
}
public class MyPagerAdapter extends PagerAdapter {
//数据源
private List<View> viewList;
private List<String> titleList;
MyPagerAdapter(List<View> viewList,List<String> titleList){
this.viewList = viewList;
this.titleList = titleList;
}
@Override
public int getCount() {
return viewList.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
return view == o;
}
/**
* 实例化一个页卡
* @param container
* @param position
* @return
*/
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
container.addView(viewList.get(position));
return viewList.get(position);
}
/**
* 销毁一个页卡
* @param container
* @param position
* @param object
*/
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView(viewList.get(position));
}
/**
* 返回页卡标题信息
* @param position
* @return
*/
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return titleList.get(position);
}
}
//4.创建PagerAdapter适配器,绑定数据源
MyPagerAdapter myPagerAdapter = new MyPagerAdapter(viewList,titleList);
//5.ViewPager绑定适配器
viewPager.setAdapter(myPagerAdapter);
//6.ViewPager添加监听器
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int i, float v, int i1) {
}
@Override
public void onPageSelected(int i) {
Toast.makeText(ViewPagerActivity.this,"第"+(i+1)+"页",Toast.LENGTH_SHORT).show();
}
@Override
public void onPageScrollStateChanged(int i) {
}
});
pagerTabStrip.setBackgroundColor(Color.GRAY);
pagerTabStrip.setTextColor(Color.BLACK);
pagerTabStrip.setTabIndicatorColor(Color.RED);
至此我们学习了四个适配器控件,接下来的文章会继续介绍更多高级控件,感谢阅读。
Github项目地址:AdapterWidget