前言
学校要求做安卓项目,想实现一个食堂点餐的app,初学Java,有很多不足,下面仅作为个人经验的分享。欢迎大佬的指点,也希望对后来的同学有用。
1. 双 ListView 布局
我碰到的第一个难题是双ListView如何实现,其实很简单,只需要在一个xml中,使用一个线性布局即可。
为了实现日后的双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\"><RelativeLayoutandroid:layout_width=\"match_parent\"android:layout_height=\"100dp\"android:padding=\"10dp\"android:background=\"@mipmap/canteenshuiyun\"><TextViewandroid:layout_width=\"wrap_content\"android:layout_height=\"wrap_content\"android:layout_marginTop=\"60dp\"android:layout_marginLeft=\"120dp\"android:text=\"当前等待人数:36\" /></RelativeLayout><LinearLayoutandroid:layout_width=\"match_parent\"android:layout_height=\"match_parent\"android:orientation=\"horizontal\"><ListViewandroid: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\"/><ListViewandroid: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\"><ImageViewandroid:id=\"@+id/item_foodcontent_iv\"android:layout_width=\"120dp\"android:layout_height=\"80dp\"android:src=\"@mipmap/ic_launcher\"android:scaleType=\"fitXY\"/><TextViewandroid: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\"/><TextViewandroid: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\"/><TextViewandroid: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\"/><ImageViewandroid: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\" /><ImageViewandroid: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//返回指定位置所对应的IDpublic long getItemId(int position) {return position;}@Overridepublic int getItemViewType(int position) {if(position%5==0){return type_foodheader;}else{return type_fooditem;}}@Overridepublic int getViewTypeCount() {return 2;}//返回指定位置所对应的View@Overridepublic 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;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_buying_food_in_shui_yun);//1.查找控件findviewbyid---下面的方法initView();//2.找到ListView-Shop的数据源------ShopUntilsmDatas = new ArrayList<>();allShopList = ShopUntils.getAllShopList();mDatas.addAll(allShopList);//--------------------------------------------//2.1 找到ListView-Food的数据源------FoodcontentUntilsmDatas_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()方法是我用来找控件的一个集成方法