android开发--ListView
ListView与Spinner在代码实现上有些相似,上一篇我写了Spinner,所以我这次写ListView,顺便比较一下这两个控件的不同之处。


一、简单的一维ListView
效果图:

首先,在app/res/values/strings.xml里添加<string-array>来存放我们需要的数据
<string-array name="listViewList">
<item>红楼梦</item>
<item>西游记</item>
<item>水浒传</item>
<item>三国演义</item>
</string-array>方法1:设置entries属性
<ListView
android:id="@+id/listView"
android:entries="@array/listViewList"
android:layout_width="match_parent"
android:layout_height="match_parent" />方法2:设置ArrayAdapter
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView mylistView=findViewById(R.id.listView);
String[] items=getResources().getStringArray(R.array.listViewList);
ArrayAdapter<String> myAdapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,items);
mylistView.setAdapter(myAdapter);
}
}然后添加点击事件:setOnItemClickListener
mylistView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getApplicationContext(),items[position].toString(),Toast.LENGTH_SHORT).show();
}
});如图所示:

二、有文字图片复选框的ListView (参考来自:ListView的简单应用,这个例子用到了javaBean,是一个很值得借鉴的例子。)
需要实现的ListView效果图如下:

首先我们需要创建一个JavaBean来包装我们的数据,新建java class,并取名MyBean.java
如下图设置三个私有变量,然后单击鼠标右键 Generate,点击构造方法Constructor,按住ctrl键点选所有的变量,点击ok插入构造方法。



同样的添加getter和setter方法,也是选中所有的变量,点击ok就插入了方法。


MyBean.java 代码如下:
public class MyBean {
private int imageID;//商品图片
private String details;//商品描述
private float price;//商品价格
public MyBean(int imageID, String details, float price) {
this.imageID = imageID;
this.details = details;
this.price = price;
}
public int getImageID() {
return imageID;
}
public void setImageID(int imageID) {
this.imageID = imageID;
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}然后我们为这个购物清单ListView的列表项设计一个布局,在app/res/layout文件夹下新建一个Layout Resource File,并取名listview_item_layout.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"
android:id="@+id/L1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ImageView
android:id="@+id/imageView"
android:layout_width="110dp"
android:layout_height="110dp"
android:padding="5dp"
app:srcCompat="@mipmap/ic_launcher" />
<TextView
android:id="@+id/tv_details"
android:layout_width="150dp"
android:layout_height="110dp"
android:padding="5dp"
android:layout_gravity="center"/>
<TextView
android:id="@+id/tv_price"
android:layout_width="0dp"
android:layout_height="110dp"
android:layout_weight="1"
android:gravity="center"
android:textStyle="bold" />
</LinearLayout>修改 activity_main.xml 如下,有一个展示商品的ListView和用来计算购物金额的Button
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="wrap_content"
android:paddingBottom="34dp">
</ListView>
<Button
android:id="@+id/jiezhang"
android:layout_gravity="bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="结账离开" />
</FrameLayout>然后准备我们将要展示的商品数据(商品图片和商品描述)
商品图片复制到app/res/drawable目录下

商品描述写在app/res/values/strings.xml 的<resource>标签里,如下的detailList
<string-array name="detailList">
<item>宝宝夏装2020新款洋气男孩衣服套装幼儿童装夏季短裙背带裤两件套</item>
<item>拇指鱼儿童卫衣2019秋季童装拼色长袖T恤套头打底衫小童圆领上衣</item>
<item>女童套装童装2020夏季新款韩版可爱猫咪蓬蓬裙儿童纱裙公主短裙</item>
<item>女童洋气网红套装2020新款韩版儿童装短袖两件套女孩时髦运动夏装</item>
<item>女童连衣裙2020新款夏季洋气装儿童宝宝小孩公主背心裙亲子美女装</item>
<item>童装男童夏天短袖套装夏装2020新款中大童小儿童网红帅洋气韩版潮</item>
<item>童装两件套2020夏装女童套装新款夏季女背带裙洋气2短袖衬衫宝宝</item>
<item>2020卡通动漫新款童装夏牛仔背带裤套装男童短袖t恤潮部落</item>
</string-array>为了让我们设计的listview_item_layout.xml、商品的数据与我们在activity_main.xml的ListView适配,我们需要自定义一个Adapter
新建一个Java Class,取名myAdapter.java ,代码如下:
public class myAdapter<T> extends ArrayAdapter {
private final int resource;
private Map<Integer,Boolean> map=new HashMap<>();
public myAdapter(@NonNull Context context, int resource, @NonNull List<MyBean> objects) {
super(context, resource, objects);
this.resource=resource;
}
@NonNull
@Override
public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
final MyBean myBean=(MyBean)getItem(position);
final View view= View.inflate(getContext(),R.layout.listview_item_layout,null);//LayoutInflater.from(getContext()).inflate(resource,parent,null);
ImageView imageView=view.findViewById(R.id.imageView);
TextView tv_details=view.findViewById(R.id.tv_details);
TextView tv_price=view.findViewById(R.id.tv_price);
final CheckBox checkBox=(CheckBox)view.findViewById(R.id.checkBox);
imageView.setImageResource(myBean.getImageID());
tv_details.setText(myBean.getDetails());
tv_price.setText("¥ "+myBean.getPrice());//以下是为了解决CheckBox状态改变的问题
checkBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (checkBox.isChecked()){
map.put(position,true);
}else {
map.remove(position);
}
}
});
if(map!=null&&map.containsKey(position)){
checkBox.setChecked(true);
}else {
checkBox.setChecked(false);
}
return view;
}
}大家可能奇怪为什么有的代码是红色加粗,其实是为了解决一个CheckBox的问题,如果删掉这段红色代码,也能运行,但是会出现滑动ListView后,勾选的复选框状态改变的问题
复选框状态改变的解决方法参考:Android ListView+CheckBox的实现
没有加上红色的代码之前:
加上红色的代码之后:
写好自定义的Adapter之后,就是最关键的一步了,让数据和ListView适配
MainActivity.java
public class MainActivity extends AppCompatActivity {
List<MyBean> myBeans=new ArrayList<>();
int[] imagesID;//商品图片的id
String[] detailsID;//商品的描述
float[] prices;//商品价格
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imagesID= new int[]{R.drawable.clothes1, R.drawable.clothes2, R.drawable.clothes3, R.drawable.clothes4, R.drawable.clothes5, R.drawable.clothes6, R.drawable.clothes7, R.drawable.clothes8};
detailsID=getResources().getStringArray(R.array.detailList);
prices= new float[]{78.0f, 160.0f, 67.5f, 188.0f, 189.0f, 79.0f, 38.0f, 68.0f};
ListView mylistView=findViewById(R.id.listView);
init();//初始化数据
myAdapter<String> myAdapter=new myAdapter<String>(this,R.layout.text,myBeans);
mylistView.setAdapter(myAdapter);
}
private void init(){//初始化数据
int i;
MyBean item;
for(i=0;i<imagesID.length;i++){
item=new MyBean(imagesID[i],detailsID[i],prices[i]);
myBeans.add(item);
}
}
}到这里为止,我们的购物清单的界面已经完成了,但是别忘了我们还有一个用来结账计算总金额的Button,那么如何得到ListView中复选框选中的项的金额呢?
就要利用CheckBox的setCheckedChangeListener来监听并计算总额
这个监听器就设置在myAdapter的getView()方法里,总金额设为全局变量,在getView方法里的得到CheckBox对象并设置监听器,修改金额,最后加上get方法使其他类可以得到这个计算好的总金额
public class myAdapter<T> extends ArrayAdapter {
private Map<Integer,Boolean> map=new HashMap<>();
private float TotalPrice=0;
public float getTotalPrice() {
return TotalPrice;
}
public myAdapter(@NonNull Context context, int resource, @NonNull List<MyBean> objects) {
super(context, resource, objects);
}
@NonNull
@Override
public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
final MyBean myBean=(MyBean)getItem(position);
final View view= View.inflate(getContext(),R.layout.text,null);
LinearLayout linearLayout=view.findViewById(R.id.L1);
ImageView imageView=view.findViewById(R.id.imageView);
TextView tv_details=view.findViewById(R.id.tv_details);
TextView tv_price=view.findViewById(R.id.tv_price);
final CheckBox checkBox=(CheckBox)view.findViewById(R.id.checkBox);
imageView.setImageResource(myBean.getImageID());
tv_details.setText(myBean.getDetails());
tv_price.setText("¥ "+myBean.getPrice());
//以下是为了解决CheckBox的问题
checkBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (checkBox.isChecked()){
map.put(position,true);
}else {
map.remove(position);
}
}
});
if(map!=null&&map.containsKey(position)){
checkBox.setChecked(true);
}else {
checkBox.setChecked(false);
}
//以下是CheckBox的改变状态触发的事件
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
TotalPrice+=myBean.getPrice();
}else{
TotalPrice-=myBean.getPrice();
}
}
});
return view;
}
} 上面红色的代码就是为CheckBox加的监听器。计算好的总金额会在Button的点击后使用,所以设置get方法得到这个值。
于是我们为Button加一个点击的监听器,下面这段代码写在MainActivity.java的onCreate()方法的最后,从myAdapter对象的get方法得到的金额,用Toast显示。
Button jiezhang=findViewById(R.id.jiezhang);
jiezhang.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),String.valueOf(myAdapter.getTotalPrice()),Toast.LENGTH_SHORT).show();
}
});实现效果如下图所示

简单的购物车功能做好啦,其实还有很多值得改进的地方,比如显示添加购买数量的可以加减的组合控件、删除购物清单的商品的按钮、页面跳转、从数据库读取数据啦巴拉巴拉的。