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 extends BaseAdapter {
    Context cxt;
    List<MyBean> itemList;
    private Map<Integer,Boolean> map=new HashMap<>();

  public myAdapter(Context cxt, List<MyBean> itemList) { //适配器需要确定:在哪个上下文环境,适配哪些数据。 this.cxt = cxt; this.itemList = itemList; } @Override public int getCount() { return itemList.size(); } @Override public Object getItem(int position) { return itemList.get(position); } @Override public long getItemId(int position) { return position; } @NonNull @Override public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) { final MyBean currentItem =(MyBean)getItem(position); final View itemview = View.inflate(cxt,R.layout.listview_item_layout,null); ImageView imageView= itemview.findViewById(R.id.imageView); TextView tv_details= itemview.findViewById(R.id.tv_details); TextView tv_price= itemview.findViewById(R.id.tv_price); final CheckBox checkBox=(CheckBox) itemview.findViewById(R.id.checkBox); imageView.setImageResource(currentItem.getImageID()); tv_details.setText(currentItem.getDetails()); tv_price.setText("¥ "+ currentItem.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 itemview; } }

大家可能奇怪为什么有的代码是红色加粗,其实是为了解决一个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,,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 extends BaseAdapter {
    Context cxt;
    List<MyBean> itemList;
    private Map<Integer,Boolean> map=new HashMap<>();
    private float TotalPrice=0;

    public myAdapter(Context cxt, List<MyBean> itemList) {
        //适配器需要确定:在哪个上下文环境,适配哪些数据。
        this.cxt = cxt;
        this.itemList = itemList;
    }

    public float getTotalPrice() {
        return TotalPrice;
    }

    @Override
    public int getCount() {
        return itemList.size();
    }

    @Override
    public Object getItem(int position) {
        return itemList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @NonNull
    @Override
    public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {

        final MyBean currentItem =(MyBean)getItem(position);
        final View itemview = View.inflate(cxt,R.layout.listview_item_layout,null);

        ImageView imageView= itemview.findViewById(R.id.imageView);
        TextView tv_details= itemview.findViewById(R.id.tv_details);
        TextView tv_price= itemview.findViewById(R.id.tv_price);
        final CheckBox checkBox=(CheckBox) itemview.findViewById(R.id.checkBox);

        imageView.setImageResource(currentItem.getImageID());
        tv_details.setText(currentItem.getDetails());
        tv_price.setText("¥ "+ currentItem.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+= currentItem.getPrice();
                }else{
                    TotalPrice-= currentItem.getPrice();
                }
            }
        });
        return itemview;
    }
}

 

上面红色的代码就是为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();
            }
        });

 实现效果如下图所示

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

posted @ 2020-05-26 11:20  ECHO_01  阅读(253)  评论(0)    收藏  举报