前言

学校要求做安卓项目,想实现一个食堂点餐的app,初学Java,有很多不足,下面仅作为个人经验的分享。欢迎大佬的指点,也希望对后来的同学有用。

1. 双 ListView 布局

我碰到的第一个难题是双ListView如何实现,其实很简单,只需要在一个xml中,使用一个线性布局即可。
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020042522253923.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzk5MDE3MQ==,size_16,color_FFFFFF,t_7
为了实现日后的双ListView联动这是必不可少的第一步,关于ListView联动我日后在写。

<?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"
    tools:context=".Shop_list.BuyingFoodInShuiYunActivity"
    android:orientation="vertical">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:padding="10dp"
        android:background="@mipmap/canteenshuiyun">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="60dp"
            android:layout_marginLeft="120dp"
            android:text="当前等待人数:36" />
    </RelativeLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">
        <ListView
            android:id="@+id/title"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:scrollbars="none" >
        </ListView>
        <View android:layout_width="1dp"
            android:background="@android:color/black"
            android:layout_height="match_parent"/>
        <ListView
            android:id="@+id/content"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="3"
            android:scrollbars="none" >
        </ListView>
    </LinearLayout>
</LinearLayout>

首先用相对布局在上方放置一个Title,再用线性布局实现下方的两个ListView.

2. ListView适配器

适配器的写法比较固定。不同的ListView可以用不同的Adapter来填充内容。

(1).item的封装

对于这方面我是用“封装”的概念理解的。比如以上述布局中的id为content的ListView为例子,首先我们需要明白其需要用什么样的XML布局去渲染每一个item.
在这里插入图片描述
就是这样啦。下附代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="wrap_content"
    android:padding="10dp"
    >

    <ImageView
        android:id="@+id/item_foodcontent_iv"
        android:layout_width="120dp"
        android:layout_height="80dp"
        android:src="@mipmap/ic_launcher"
        android:scaleType="fitXY"/>
    <TextView
        android:id="@+id/item_foodcontent_tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/item_foodcontent_iv"
        android:layout_marginTop="10dp"
        android:text="food"
        android:layout_marginLeft="10dp"
        android:textStyle="bold"
        android:textSize="20sp"/>
    <TextView
        android:id="@+id/item_foodcontent_tv_titlenumber"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/item_foodcontent_tv_title"
        android:text="x"
        android:layout_marginTop="10dp"
        android:textStyle="bold"
        android:textSize="20sp"
        android:layout_marginLeft="10dp"/>

    <TextView
        android:id="@+id/item_foodcontent_tv_simple_introduction"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@id/item_foodcontent_tv_title"
        android:layout_alignBottom="@id/item_foodcontent_iv"
        android:text="A simple introduction of the food"/>

    <ImageView
        android:id="@+id/item_foodcontent_iv_next"
        android:layout_width="28dp"
        android:layout_height="46dp"
        android:layout_marginTop="0dp"
        android:layout_alignParentRight="true"
        android:src="@mipmap/expend" />
    <ImageView
        android:id="@+id/item_foodcontent_iv_addbutton"
        android:layout_width="28dp"
        android:layout_height="46dp"
        android:src="@mipmap/addbutton"
        android:layout_alignParentRight="true"
        android:layout_marginTop="45dp"/>
</RelativeLayout>

给每一个部分,取上规定好的id,方便我们日后查找。
弄明白我们的布局后,下面封装的内容就非常清楚了。
我们将XML封装的Java类命名为:FoodContentBean

package com.example.buyfood.Bean;

public class FoodContentBean {
    private String foodName;
    private String foodIntroduce;
    private String foodNumber;
    private int picID;
    //下面是类别
    private String type;
    private String typenumber;

    public FoodContentBean(String foodName, String foodIntroduce, String foodNumber, int picID) {
        this.foodName = foodName;
        this.foodIntroduce = foodIntroduce;
        this.foodNumber = foodNumber;
        this.picID = picID;
    }
    public FoodContentBean(String type, String typenumber) {
        this.type = type;
        this.typenumber = typenumber;
    }

    public FoodContentBean() {
    }

    public String getFoodName() {
        return foodName;
    }

    public void setFoodName(String foodName) {
        this.foodName = foodName;
    }

    public String getFoodIntroduce() {
        return foodIntroduce;
    }

    public void setFoodIntroduce(String foodIntroduce) {
        this.foodIntroduce = foodIntroduce;
    }

    public String getFoodNumber() {
        return foodNumber;
    }

    public void setFoodNumber(String foodNumber) {
        this.foodNumber = foodNumber;
    }

    public int getPicID() {
        return picID;
    }

    public void setPicID(int picID) {
        this.picID = picID;
    }

    //下面是类别的getset方法
    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getTypenumber() {
        return typenumber;
    }

    public void setTypenumber(String typenumber) {
        this.typenumber = typenumber;
    }
}

其中的变量就是我们布局中的图片、文字、按钮(其实也是图片)。
设置好构造方法,设置好get、set方法即可。

(2).资源的获取

我们初学,项目一般处于本地获取资源的状态,我们直接把资源写到代码当中!命名为:FoodContentUtils

package com.example.buyfood.Bean;

import com.example.buyfood.R;

import java.util.ArrayList;
import java.util.List;

public class FoodContentUtils {
    private static final int[] FoodpicID = {R.mipmap.ic_launcher_round};
    public static List<FoodContentBean> getAllFoodList(){
        List<FoodContentBean> list = new ArrayList<>();
        //食物
        String foodname = "食物";
        String foodnumber;
        int Foodnumber = 1;
        String foodintroduce = "该处是食物简介";
        int picID = FoodpicID[0];
        //---------------------------------------
        //类别
        String type = "店铺";
        String typenumber;
        int Typenumber=1;
        //---------------------------------------
        for(int i=0;i<45;i++)
        {
            if(i%5==0)
            {
                typenumber = String.valueOf(Typenumber);
                Typenumber++;
                FoodContentBean bean = new FoodContentBean(type,typenumber);
                list.add(bean);
            }
            else
            {
                foodnumber = String.valueOf(Foodnumber);
                Foodnumber++;
                FoodContentBean bean = new FoodContentBean(foodname,foodintroduce,foodnumber,picID);
                list.add(bean);
            }

        }
        return list;
    }
}

注意了,我在这里运用了一些比较简单的方法去规定资源List的内容,即重写FoodContentBean的构造方法,因为我们要分层实现该ListView.下面将说明这一点。

(3). Adapter写法

FoodListAdapter是BaseAdapter的子类,所以我们首先要继承它。再去实现重要的方法。

package com.example.buyfood.Shop_list;

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.example.buyfood.Bean.FoodContentBean;
import com.example.buyfood.R;

import java.util.List;

public class FoodListAdapter extends BaseAdapter {
    Context context;
    List<FoodContentBean> mDatas;
    private static final int type_foodheader = 0;
    private static final int type_fooditem = 1;




    public FoodListAdapter(Context context, List<FoodContentBean> mDatas) {
        this.context = context;
        this.mDatas = mDatas;
    }

    @Override
    //  getCount决定了ListView展示的行数
    public int getCount() {
        return mDatas.size();
    }

    @Override
    //返回指定位置所对应的的数据
    public Object getItem(int position) {
        return mDatas.get(position);
    }

    @Override
    //返回指定位置所对应的ID
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemViewType(int position) {
        if(position%5==0)
        {
            return type_foodheader;
        }else{
            return type_fooditem;
        }
    }

    @Override
    public int getViewTypeCount() {
        return 2;
    }

    //返回指定位置所对应的View
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        int item_type = getItemViewType(position);
        ViewHolder holder = null;
        ViewHolder_foodheader holder_foodheader = null;
        if(convertView==null)//将布局转化为view对象的方法
        {
            switch (item_type)
            {
                case type_foodheader:
                    convertView = LayoutInflater.from(context).inflate(R.layout.item_foodheader,null);
                    holder_foodheader = new ViewHolder_foodheader(convertView);
                    convertView.setTag(holder_foodheader);
                    break;
                case type_fooditem:
                    convertView = LayoutInflater.from(context).inflate(R.layout.item_foodcontent_list,null);
                    holder = new ViewHolder(convertView);
                    convertView.setTag(holder);
                    break;
            }
        } else{
            switch (item_type)
            {
                case type_foodheader:
                    holder_foodheader = (ViewHolder_foodheader)convertView.getTag();
                    break;
                case type_fooditem:
                    holder = (ViewHolder)convertView.getTag();
                    break;
            }
        }
        //加载控件中的显示
        //获取集合指定位置的数据
        switch (item_type)
        {
            case type_foodheader:
                FoodContentBean foodContentBean = mDatas.get(position);
                holder_foodheader.typename.setText(foodContentBean.getType());
                holder_foodheader.typenumber.setText(foodContentBean.getTypenumber());
                break;
            case type_fooditem:
                FoodContentBean foodcontentBean = mDatas.get(position);
                holder.foodname.setText(foodcontentBean.getFoodName());
                holder.foodpic.setImageResource(foodcontentBean.getPicID());
                holder.foodintroduce.setText(foodcontentBean.getFoodIntroduce());
                holder.foodnumber.setText(foodcontentBean.getFoodNumber());
                break;
        }
        return convertView;
    }

    class ViewHolder{
        TextView foodname,foodnumber,foodintroduce;
        ImageView foodpic;
        public ViewHolder(View view){
            foodname = view.findViewById(R.id.item_foodcontent_tv_title);
            foodnumber = view.findViewById(R.id.item_foodcontent_tv_titlenumber);
            foodintroduce = view.findViewById(R.id.item_foodcontent_tv_simple_introduction);
            foodpic = view.findViewById(R.id.item_foodcontent_iv);
        }
    }
    class ViewHolder_foodheader{
        TextView typename,typenumber;
        public ViewHolder_foodheader(View view){
            typename = view.findViewById(R.id.item_foodheader_tv_fh);
            typenumber = view.findViewById(R.id.item_foodheader_tv_fhn);
        }
    }
}

还记得我们资源添加为什么要用奇怪的判断语句吗?

            if(i%5==0)
            {
                typenumber = String.valueOf(Typenumber);
                Typenumber++;
                FoodContentBean bean = new FoodContentBean(type,typenumber);
                list.add(bean);
            }
            else
            {
                foodnumber = String.valueOf(Foodnumber);
                Foodnumber++;
                FoodContentBean bean = new FoodContentBean(foodname,foodintroduce,foodnumber,picID);
                list.add(bean);
            }

这是因为我们后来的adapter中,position会随着我们的适配次数不断递增,如果我们没有提前规定好分类标题的位置,会出现位置被占用的情况,当然这是一个笨办法。

(4). 最后创建适配器
package com.example.buyfood.Shop_list;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.ListView;

import com.example.buyfood.Bean.FoodContentBean;
import com.example.buyfood.Bean.FoodContentUtils;
import com.example.buyfood.Bean.ShopBean;
import com.example.buyfood.Bean.ShopUntils;
import com.example.buyfood.R;

import java.util.ArrayList;
import java.util.List;

public class BuyingFoodInShuiYunActivity extends AppCompatActivity {
    ListView show_Lv_title,show_Lv_foodcontent;//展示第一、第二个ListView
    //ListView-shoptitle的数据源
    List<ShopBean> mDatas;
    List<ShopBean> allShopList;
    private ShopListAdapter adapter;
    //ListView-foodcontent的数据源
    List<FoodContentBean> mDatas_food;
    List<FoodContentBean> allFoodList;
    private FoodListAdapter adapter_food;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_buying_food_in_shui_yun);
        //1.查找控件findviewbyid---下面的方法
        initView();
        //2.找到ListView-Shop的数据源------ShopUntils
        mDatas = new ArrayList<>();
        allShopList = ShopUntils.getAllShopList();
        mDatas.addAll(allShopList);
        //--------------------------------------------
        //2.1 找到ListView-Food的数据源------FoodcontentUntils
        mDatas_food = new ArrayList<>();
        allFoodList = FoodContentUtils.getAllFoodList();
        mDatas_food.addAll(allFoodList);
        //3.创建适配器 BaseAdapter的子类
        adapter = new ShopListAdapter(this, mDatas);
        //---------------------------------------------------------
        //另一个适配器
        adapter_food = new FoodListAdapter(this,mDatas_food);
        //4.设置适配器
        show_Lv_title.setAdapter(adapter);
        show_Lv_foodcontent.setAdapter(adapter_food);
    }

    private void initView() {
        show_Lv_title = findViewById(R.id.title);
        show_Lv_foodcontent = findViewById(R.id.content);
    }
}

备注:initview()方法是我用来找控件的一个集成方法

最终效果:

在这里插入图片描述

欢迎批评指正!

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐