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(); } });
实现效果如下图所示
简单的购物车功能做好啦,其实还有很多值得改进的地方,比如显示添加购买数量的可以加减的组合控件、删除购物清单的商品的按钮、页面跳转、从数据库读取数据啦巴拉巴拉的。