学习过程感觉比较难以介绍,直接上练习题目,说下新建过程。(题目自定)
练习题目
仿wx做个界面,显示微信消息的界面
步骤
1. 准备主Layout布局
主要是用于显示列表的界面,就是一个大的容器。
res/lauout/activity_list_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ListViewActivity">
<ListView
android:id="@+id/lv_one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
2、新建listview的itm布局
在第1步已经准备好容器了,那就需要在容器内放明细itm。看图中每个itm内有不同元素,可以把itm看成一个layout,所以需要准备itm的layout
文件 res/layout/list_view_itm.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="80dp">
<ImageView
android:id="@+id/iv_lv_itm_one"
android:layout_width="80dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:src="@drawable/ic_baseline_5g_24" />
<TextView
android:id="@+id/tv_lv_itm_three"
android:layout_width="60dp"
android:layout_height="40dp"
android:gravity="center_vertical"
android:layout_alignParentRight="true"
android:text="three" />
<TextView
android:id="@+id/tv_lv_itm_four"
android:layout_width="60dp"
android:layout_height="match_parent"
android:layout_below="@+id/tv_lv_itm_three"
android:layout_alignRight="@+id/tv_lv_itm_three"
android:gravity="center_vertical"
android:text="four" />
<TextView
android:id="@+id/tv_lv_itm_one"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_toLeftOf="@+id/tv_lv_itm_three"
android:layout_toRightOf="@+id/iv_lv_itm_one"
android:gravity="center_vertical"
android:text="one"
android:textSize="30sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_lv_itm_two"
android:text="two"
android:textSize="20sp"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_below="@+id/tv_lv_itm_one"
android:layout_toLeftOf="@+id/tv_lv_itm_four"
android:layout_toRightOf="@+id/iv_lv_itm_one"
android:gravity="center_vertical" />
</RelativeLayout>
</LinearLayout>
新建bean类(定义明细各部分内容)
明细itm的样式布局准备好了,接下来需要准备明细的数据类,定义明细内容。那新建一个bean类。
文件com/pha/first/bean/Bean.java
新建Bean过程
- 添加对应的五个元素,元素类型根据界面的内容而定
- 增加元素的Getter and Setter (在类里alt+insert ,部分电脑需要fn+alt+insert)
- 至于setBean这个方法是,后面练习中感觉一个一个的赋值比较麻烦,提起出来的
适配器com/pha/first/bean/Bean.java最终代码
package com.pha.first.bean;
import android.graphics.drawable.Drawable;
public class Bean {
Drawable img;
String name;
String message;
String datetime;
String tip;
public Drawable getImg() {
return img;
}
public void setImg(Drawable img) {
this.img = img;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getDatetime() {
return datetime;
}
public void setDatetime(String datetime) {
this.datetime = datetime;
}
public String getTip() {
return tip;
}
public void setTip(String tip) {
this.tip = tip;
}
public void setBean(Drawable img,String name,String message,String datetime,String tip){
this.img=img;
this.name=name;
this.message=message;
this.datetime=datetime;
this.tip=tip;
}
}
4、准备明细数据
将每个明细itm的具体内容。
com/pha/first/ListViewActivity.java 中新建方法InitData()方法,并在onCreate()调用该方法。
- 全局私有变量(数据存放的变量)
private List<Bean> data = new ArrayList<>();
- 定义InitData()方法
private void InitData(){
for(int i = 0; i < 100 ; i++){
Bean bean = new Bean();
switch (i%5){
case 0:
bean.setBean(getResources().getDrawable(R.drawable.ic_baseline_person_24),"李白"+i,"举头望明月,低头思故乡","唐朝","绝句");
break;
case 1:
bean.setBean(getResources().getDrawable(R.drawable.ic_baseline_lock_24),"苏轼"+i,"明月几时有,把酒问青天","宋朝","宋词");
break;
case 2:
bean.setBean(getResources().getDrawable(R.drawable.ic_baseline_search_24),"龚自珍"+i,"我劝天公重抖擞,不拘一格降人才","清朝","已亥杂诗");
break;
case 3:
bean.setBean(getResources().getDrawable(R.drawable.ic_launcher_background),"鲁迅"+i,"寄意寒星荃不察,我以我血荐轩辕","近代","近代诗");
break;
case 4:
bean.setBean(getResources().getDrawable(R.drawable.ic_baseline_west_24),"毛泽东"+i,"怅寥廓,问苍茫大地,谁主沉浮?","现代","词");
break;
default:
break;
}
data.add(bean);
}
}
5、新建适配器(视图和数据间的联系/桥梁)
-
新建adapter:com/pha/first/adapter/TestAdapter.java(名字我自己随意定的)
-
新建TestAdapter.java后需要集成BaseAdapter。
这时会提示错误。需要重写四个方法:getCount()、getItem()、getItemId()、getView() -
定义数据lt_data(界面需要数据的,器数据类型就是List,Bean就是刚才定义数据类)、context(视图,就是显示的容器界面视图)
-
构造函数TestAdapter:
在TestAdapter.java类里alt+insert(部分电脑需要fn+alt+insert)
- 修改getCount()的返回值:lt_data.size(); 就是返回数据长度
- 修改getItemId()的返回值:返回参数即可;返回点击记录的位置(第几条)
- 修改getView(): 这个方法主要是将数据放到视图中。
修改getView的思路大概是
1、获取视图。
view = LayoutInflater.from(context).inflate(R.layout.list_view_itm, viewGroup, false);
其中view是调用方法是传进来的参数。但是由于这个数据是逐条添加到视图中,避免view重复获取,所以这句话改为
if (view==null) {
view = LayoutInflater.from(context).inflate(R.layout.list_view_itm, viewGroup, false);
}
2、获取明细视图(view,也是list_view_itm.xml)中个元素id,并且赋值
适配器TestAdapter.java最终代码
package com.pha.first.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.pha.first.R;
import com.pha.first.bean.Bean;
import java.util.List;
public class TestAdapter extends BaseAdapter {
private List<Bean> lt_data;
private Context context;
public TestAdapter(List<Bean> lt_data, Context context) {
this.lt_data = lt_data;
this.context = context;
}
@Override
public int getCount() {
return lt_data.size();
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (view==null) {
view = LayoutInflater.from(context).inflate(R.layout.list_view_itm, viewGroup, false);
}
// 获取list_view_itm中的元素
ImageView iv_lv_itm_one = view.findViewById(R.id.iv_lv_itm_one);
TextView tv_lv_itm_one = view.findViewById(R.id.tv_lv_itm_one);
TextView tv_lv_itm_two = view.findViewById(R.id.tv_lv_itm_two);
TextView tv_lv_itm_three = view.findViewById(R.id.tv_lv_itm_three);
TextView tv_lv_itm_four = view.findViewById(R.id.tv_lv_itm_four);
iv_lv_itm_one.setImageDrawable(lt_data.get(i).getImg());
tv_lv_itm_one.setText(lt_data.get(i).getName());
tv_lv_itm_two.setText(lt_data.get(i).getMessage());
tv_lv_itm_three.setText(lt_data.get(i).getDatetime());
tv_lv_itm_four.setText(lt_data.get(i).getTip());
return view;
}
}
6、视图显示
在com/pha/first/ListViewActivity.java 中新建方法ShowListView()方法,并在onCreate()调用该方法。
private void ShowListView() {
ListView lv_one = findViewById(R.id.lv_one);
//调用adapter适配器,将数据data显示到当前视图
lv_one.setAdapter(new TestAdapter(data, this));
//ListView 的明细的点击事件
lv_one.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Log.e(TAG, "onItemClick: "+i +" 记录"+data.get(i).getName()+":"+data.get(i).getMessage());
}
});
}
视图ListViewActivity.java最终代码
package com.pha.first;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import com.pha.first.adapter.TestAdapter;
import com.pha.first.bean.Bean;
import java.util.ArrayList;
import java.util.List;
public class ListViewActivity extends AppCompatActivity {
private static final String TAG = "ListView";
private List<Bean> data = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view);
//数据初始化
InitData();
//展示ListView 数据
ShowListView();
}
private void ShowListView() {
ListView lv_one = findViewById(R.id.lv_one);
//调用adapter适配器,将数据data显示到当前视图
lv_one.setAdapter(new TestAdapter(data, this));
//ListView 的明细的点击事件
lv_one.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Log.e(TAG, "onItemClick: "+i +" 记录"+data.get(i).getName()+":"+data.get(i).getMessage());
}
});
}
private void InitData(){
for(int i = 0; i < 100 ; i++){
Bean bean = new Bean();
switch (i%5){
case 0:
bean.setBean(getResources().getDrawable(R.drawable.ic_baseline_person_24),"李白"+i,"举头望明月,低头思故乡","唐朝","绝句");
break;
case 1:
bean.setBean(getResources().getDrawable(R.drawable.ic_baseline_lock_24),"苏轼"+i,"明月几时有,把酒问青天","宋朝","宋词");
break;
case 2:
bean.setBean(getResources().getDrawable(R.drawable.ic_baseline_search_24),"龚自珍"+i,"我劝天公重抖擞,不拘一格降人才","清朝","已亥杂诗");
break;
case 3:
bean.setBean(getResources().getDrawable(R.drawable.ic_launcher_background),"鲁迅"+i,"寄意寒星荃不察,我以我血荐轩辕","近代","近代诗");
break;
case 4:
bean.setBean(getResources().getDrawable(R.drawable.ic_baseline_west_24),"毛泽东"+i,"怅寥廓,问苍茫大地,谁主沉浮?","现代","词");
break;
default:
break;
}
data.add(bean);
}
}
}
7、运行效果图
8、优化
回过头来在看TestAdapter.java中的getView()方法(即数据赋值到视图),在这个过程中,每条明细都需要获取list_view_itm.xml中的各元素id,就导致每次获取id时会浪费时间。
为了避免重复获取id,将id定义最终变量。
- 新增方法ViewHolder ()
private final class ViewHolder {
ImageView iv_lv_itm_one;
TextView tv_lv_itm_one ;
TextView tv_lv_itm_two ;
TextView tv_lv_itm_three ;
TextView tv_lv_itm_four ;
}
- 修改getView()
在第一个明细添加到view中时,即view==null时直接获取list_view_itm.xml的元素id,并存储。第二条添加view时,直接使用之前存储的各元素id。
适配器TestAdapter.java优化后的最终代码
package com.pha.first.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.pha.first.R;
import com.pha.first.bean.Bean;
import java.util.List;
public class TestAdapter extends BaseAdapter {
private List<Bean> lt_data;
private Context context;
public TestAdapter(List<Bean> lt_data, Context context) {
this.lt_data = lt_data;
this.context = context;
}
@Override
public int getCount() {
return lt_data.size();
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder ;
if (view==null) {
viewHolder = new ViewHolder();
view = LayoutInflater.from(context).inflate(R.layout.list_view_itm, viewGroup, false);
// 获取list_view_itm中的元素
viewHolder.iv_lv_itm_one = view.findViewById(R.id.iv_lv_itm_one);
viewHolder.tv_lv_itm_one = view.findViewById(R.id.tv_lv_itm_one);
viewHolder.tv_lv_itm_two = view.findViewById(R.id.tv_lv_itm_two);
viewHolder.tv_lv_itm_three = view.findViewById(R.id.tv_lv_itm_three);
viewHolder.tv_lv_itm_four = view.findViewById(R.id.tv_lv_itm_four);
}else{
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.iv_lv_itm_one.setImageDrawable(lt_data.get(i).getImg());
viewHolder.tv_lv_itm_one.setText(lt_data.get(i).getName());
viewHolder.tv_lv_itm_two.setText(lt_data.get(i).getMessage());
viewHolder.tv_lv_itm_three.setText(lt_data.get(i).getDatetime());
viewHolder.tv_lv_itm_four.setText(lt_data.get(i).getTip());
return view;
}
private final class ViewHolder {
ImageView iv_lv_itm_one;
TextView tv_lv_itm_one ;
TextView tv_lv_itm_two ;
TextView tv_lv_itm_three ;
TextView tv_lv_itm_four ;
}
}