标签:
这篇随身笔带来的是结合聚合数据“菜谱大全”做的一个菜谱可折叠一级+二级列表。
先发来一些截图一睹为快吧。
ExpandableListView 可用于折叠型菜单列表,其布局主要通过getGroupView和getChildView两种的重写来实现。在子列表项目比较多的情况下,可以通过GridView来布局子列表。
下面来说说ExpandableListView的适配器ExpandableListadapter的一些变量和方法:
一、首先:我们知道ExpandableListView分为父列表和子列表,其中 父列表通过一维数组String[]进行数据填充,子类表通过二维数组String[][]填充。
ExpandableListadapter重要的方法:
public long getGroupId(int groupPosition) 根据groupPosition获取与该组相关联的标识
public Object getGroup(int groupPosition) 获取与在给定组相关的数据。
public int getGroupCount() 返回Group的组数目。
getChildId (int groupPosition, int childPosition) 获取与在给定组给予孩子相关的数据。
getChildrenCount (int groupPosition) 返回在指定Group的Child数目。
public long getChildId(int groupPosition, int childPosition) 获取与在给定组给予孩子相关联的标识。
public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
ViewGroup parent) 对父列表视图进行布局。
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
ViewGroup parent) 对应于指定位置的子视图布局。
girdview用来进行网格布局,个人认为,主要girdview用于项目数较多的场景,多用于图片加文字的布局方式。,其布局优点:呈现的信息量大,一目了然。这里采用比较简单适配器SimpleAdapter。
SimpleAdapter(context, data, resource, from, to);
context 传入一个Content对象 ,
date List<? extends Map<String, ?>>的集合;
from(new string[]{...}) 一个String类型的数组,该数组的元素为GridView的items;
to(new int[...]) 一个int数组,对应布局文件的控件资源ID,并且其顺序和上一个参数每一项一一对应。
二、下面是我结合聚合数据中的“菜谱大全"的数据做的一个菜单导航。
1、菜单分类的获取:
这里省略一些过程,聚合数据sdk需要在AndroidMainFest.xml进行配置,否则程序不能正确运行。关于聚合sdk的使用请查阅聚合数据官网文档。下面直接上代码。
1 import java.util.ArrayList; 2 3 public class FoodMenu { 4 5 private int resultcode;//数据错误返回码 6 private String reason;//数据错误原因 7 private ArrayList<FirstFoodMenu >result;//返回数据 8 public int getResultcode() { 9 return resultcode; 10 } 11 public void setResultcode(int resultcode) { 12 this.resultcode = resultcode; 13 } 14 public String getReason() { 15 return reason; 16 } 17 public void setReason(String reason) { 18 this.reason = reason; 19 } 20 public ArrayList<FirstFoodMenu> getResult() { 21 return result; 22 } 23 public void setResult(ArrayList<FirstFoodMenu> result) { 24 this.result = result; 25 } 26 }
一级菜单实体类FirstFoodMenu
1 package com.example.bean; 2 3 import java.util.ArrayList; 4 5 public class FirstFoodMenu { 6 private String parentId; 7 private String name; 8 private ArrayList<SecondFoodMenu> list; 9 10 public String getParentId() { 11 return parentId; 12 } 13 14 public void setParentId(String parentId) { 15 this.parentId = parentId; 16 } 17 18 public String getName() { 19 return name; 20 } 21 22 public void setName(String name) { 23 this.name = name; 24 } 25 26 public ArrayList<SecondFoodMenu> getSecondFoodMenus() { 27 return list; 28 } 29 30 public void setSecondFoodMenus(ArrayList<SecondFoodMenu> list) { 31 this.list = list; 32 } 33 }
1 package com.example.bean; 2 3 public class SecondFoodMenu { 4 private int id; 5 private String name; 6 private int parentId; 7 8 public int getId() { 9 return id; 10 } 11 12 public void setId(int id) { 13 this.id = id; 14 } 15 16 public String getName() { 17 return name; 18 } 19 20 public void setName(String name) { 21 this.name = name; 22 } 23 24 public int getParentId() { 25 return parentId; 26 } 27 28 public void setParentId(int parentId) { 29 this.parentId = parentId; 30 } 31 32 @Override 33 public String toString() { 34 return "SecondFoodMenu [id=" + id + ", name=" + name + ", parentId=" + parentId + "]"; 35 } 36 37 }
1 package com.example.parser; 2 3 import org.json.JSONException; 4 import org.json.JSONObject; 5 6 public abstract class DataParser { 7 protected String parserError(String s) { 8 String result=null; 9 try { 10 JSONObject jsonObject = new JSONObject(s); 11 12 int errorCode = jsonObject.getInt("error_code"); 13 if (isSuccess(errorCode)) { 14 result= jsonObject.optString("result"); 15 if (result == null) 16 return "{\"code\":0}"; 17 } 18 } catch (JSONException e) { 19 e.printStackTrace(); 20 } 21 return result; 22 } 23 24 public abstract Object parser(String paramString, int paramInt); 25 26 public abstract boolean isSuccess(int paramInt); 27 }
1 package com.example.parser; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 import com.example.bean.FirstFoodMenu; 6 import com.google.gson.Gson; 7 import com.google.gson.JsonSyntaxException; 8 import com.google.gson.reflect.TypeToken; 9 import android.content.Context; 10 import android.widget.Toast; 11 12 public class FoodMenuParser extends DataParser { 13 private Context context; 14 15 public FoodMenuParser(Context context) { 16 this.context = context; 17 } 18 19 @SuppressWarnings("unchecked") 20 @Override 21 public List<FirstFoodMenu> parser(String s, int paramInt) { 22 String result = parserError(s); 23 try { 24 if ((result != null) && (!result.equals(""))) { 25 Gson gson = new Gson(); 26 return (List<FirstFoodMenu>) gson.fromJson(result, new TypeToken<List<FirstFoodMenu>>() { 27 }.getType()); 28 } 29 } catch (JsonSyntaxException e) { 30 e.printStackTrace(); 31 } 32 return null; 33 } 34 public String[][] secondParser(ArrayList<FirstFoodMenu> f){ 35 36 37 return null; 38 39 } 40 @Override 41 public boolean isSuccess(int errorCode) { 42 // TODO Auto-generated method stub 43 boolean b = false; 44 switch (errorCode) { 45 case 0: 46 b = true; 47 break; 48 case 204601: 49 Toast.makeText(this.context, "菜谱名称不能为空", 0).show(); 50 break; 51 case 204602: 52 Toast.makeText(this.context, "查询不到相关信息", 0).show(); 53 break; 54 case 204603: 55 Toast.makeText(this.context, "菜谱名过长", 0).show(); 56 break; 57 case 204604: 58 Toast.makeText(this.context, "错误的标签ID", 0).show(); 59 break; 60 case 204605: 61 Toast.makeText(this.context, "查询不到数据", 0).show(); 62 break; 63 case 204606: 64 Toast.makeText(this.context, "查询失败", 0).show(); 65 break; 66 default: 67 Toast.makeText(this.context, "查询失败", 0).show(); 68 break; 69 } 70 71 return b; 72 } 73 74 }
1 package com.example.adapter; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 6 import com.example.lifecover.R; 7 import android.content.Context; 8 import android.graphics.Color; 9 import android.graphics.drawable.ColorDrawable; 10 import android.util.Log; 11 import android.view.LayoutInflater; 12 import android.view.View; 13 import android.view.ViewGroup; 14 import android.widget.AdapterView; 15 import android.widget.BaseExpandableListAdapter; 16 import android.widget.GridView; 17 import android.widget.ImageView; 18 import android.widget.LinearLayout; 19 import android.widget.RelativeLayout; 20 import android.widget.SimpleAdapter; 21 import android.widget.TextView; 22 import android.widget.Toast; 23 24 public class FoodMenuAdapter extends BaseExpandableListAdapter { 25 Context context; 26 private String[] group; 27 private String[][] child; 28 int[] group_state_array = new int[] { R.drawable.group_up, R.drawable.group_down }; 29 private LayoutInflater mInflater; 30 31 public FoodMenuAdapter(Context context, String[] group, String[][] child) { 32 mInflater = LayoutInflater.from(context); 33 this.context = context; 34 this.group = group; 35 this.child = child; 36 } 37 38 @Override 39 public int getGroupCount() { 40 return group.length; 41 } 42 43 @Override 44 public int getChildrenCount(int groupPosition) { 45 return 1; 46 } 47 48 @Override 49 public Object getGroup(int groupPosition) { 50 return group[groupPosition]; 51 } 52 53 @Override 54 public Object getChild(int groupPosition, int childPosition) { 55 // TODO Auto-generated method stub 56 return null; 57 } 58 59 @Override 60 public long getGroupId(int groupPosition) { 61 // TODO Auto-generated method stub 62 return groupPosition; 63 } 64 65 @Override 66 public long getChildId(int groupPosition, int childPosition) { 67 // TODO Auto-generated method stub 68 return childPosition; 69 } 70 71 @Override 72 public boolean hasStableIds() { 73 return true; 74 } 75 76 /** 77 * 显示:group 78 */ 79 @Override 80 public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { 81 // 为视图对象指定布局 82 convertView = (LinearLayout) LinearLayout.inflate(context, R.layout.foodmenu_group_layout, null); 83 RelativeLayout myLayout = (RelativeLayout) convertView.findViewById(R.id.group_layout); 84 // 用来显示一级标签上的标题信息 85 TextView group_title = (TextView) convertView.findViewById(R.id.group_title); 86 // 用来显示一级标签上的大体描述的信息 87 ImageView group_state = (ImageView) convertView.findViewById(R.id.group_state); 88 // 设置标题上的文本信息 89 group_title.setText(group[groupPosition]); 90 // 设置整体描述上的文本信息 91 92 if (!isExpanded) { 93 group_state.setBackgroundResource(group_state_array[0]); 94 myLayout.setBackgroundResource(R.drawable.text_item_top_bg); 95 } else { 96 myLayout.setBackgroundResource(R.drawable.text_item_bg); 97 group_state.setBackgroundResource(group_state_array[1]); 98 } // 返回一个布局对象 99 return convertView; 100 101 } 102 103 /** 104 * 显示:child 105 */ 106 @Override 107 public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, 108 ViewGroup parent) { 109 // TODO Auto-generated method stub 110 if (convertView == null) { 111 mViewChild = new ViewChild(); 112 convertView = mInflater.inflate(R.layout.foodmenu_child_layout, null); 113 mViewChild.gridView = (GridView) convertView.findViewById(R.id.channel_item_child_gridView); 114 convertView.setTag(mViewChild); 115 } else { 116 mViewChild = (ViewChild) convertView.getTag(); 117 } 118 119 SimpleAdapter mSimpleAdapter = new SimpleAdapter(context, setGridViewData(child[groupPosition]), 120 R.layout.item_child_gridview, new String[] { "channel_gridview_item" }, 121 new int[] { R.id.channel_gridview_item }); 122 mViewChild.gridView.setAdapter(mSimpleAdapter); 123 setGridViewListener(mViewChild.gridView); 124 mViewChild.gridView.setSelector(new ColorDrawable(Color.TRANSPARENT)); 125 return convertView; 126 } 127 128 ViewChild mViewChild; 129 130 static class ViewChild { 131 TextView textView; 132 GridView gridView; 133 } 134 135 @Override 136 public boolean isChildSelectable(int groupPosition, int childPosition) { 137 return false; 138 } 139 140 /** 141 * 设置gridview点击事件监听 142 * 143 * @param gridView 144 */ 145 private void setGridViewListener(final GridView gridView) { 146 gridView.setOnItemClickListener(new GridView.OnItemClickListener() { 147 @Override 148 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 149 // TODO Auto-generated method stub 150 if (view instanceof TextView) { 151 // 如果想要获取到哪一行,则自定义gridview的adapter,item设置2个textview一个隐藏设置id,显示哪一行 152 TextView tv = (TextView) view; 153 Toast.makeText(context, "position=" + position + "||" + tv.getText(), Toast.LENGTH_SHORT).show(); 154 Log.e("hefeng", "gridView listaner position=" + position + "||text=" + tv.getText()); 155 } 156 } 157 }); 158 } 159 160 /** 161 * 设置gridview数据 162 * 163 * @param data 164 * @return 165 */ 166 private ArrayList<HashMap<String, Object>> setGridViewData(String[] data) { 167 ArrayList<HashMap<String, Object>> gridItem = new ArrayList<HashMap<String, Object>>(); 168 for (int i = 0; i < data.length; i++) { 169 HashMap<String, Object> hashMap = new HashMap<String, Object>(); 170 hashMap.put("channel_gridview_item", data[i]); 171 gridItem.add(hashMap); 172 } 173 return gridItem; 174 } 175 176 }
package com.example.view; import android.content.Context; import android.util.AttributeSet; import android.widget.GridView; public class CustomGridView extends GridView { public CustomGridView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } }
1 package com.example.lifecover; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.FileInputStream; 5 import java.io.FileOutputStream; 6 import java.util.ArrayList; 7 import java.util.List; 8 9 import com.example.adapter.FoodMenuAdapter; 10 import com.example.bean.FirstFoodMenu; 11 import com.example.bean.SecondFoodMenu; 12 import com.example.parser.FoodMenuParser; 13 import com.thinkland.sdk.android.DataCallBack; 14 import com.thinkland.sdk.android.JuheData; 15 import android.app.Activity; 16 import android.app.Dialog; 17 import android.content.Context; 18 import android.os.Bundle; 19 import android.view.LayoutInflater; 20 import android.view.View; 21 import android.view.ViewGroup; 22 import android.view.View.OnClickListener; 23 import android.view.Window; 24 import android.widget.ExpandableListView; 25 import android.widget.ImageView; 26 import android.widget.TextView; 27 import android.widget.Toast; 28 import android.widget.ExpandableListView.OnGroupExpandListener; 29 30 public class FoodActivity extends Activity implements OnClickListener { 31 private ImageView iv_back; 32 private TextView tv_title; 33 private FoodActivity mContext; 34 private Dialog loadingDialog; 35 private String[] strings;// 一级菜单分类数组 36 private String[] strings2;// 一级菜单分类id数组 37 private String[][] strings3;// 二级菜单分类数组 38 private ExpandableListView listView; 39 private FoodMenuAdapter adapter; 40 41 @Override 42 protected void onCreate(Bundle savedInstanceState) { 43 super.onCreate(savedInstanceState); 44 requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); 45 setContentView(R.layout.activity_food); 46 getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title); 47 mContext = this; 48 initView(); 49 50 51 } 52 53 private void showLoadingDialog() { 54 if (this.loadingDialog != null) { 55 this.loadingDialog.show(); 56 return; 57 } 58 this.loadingDialog = new Dialog(this.mContext, R.style.dialog_loading); 59 View view = LayoutInflater.from(this.mContext).inflate(R.layout.dialog_loading, null); 60 this.loadingDialog.setContentView(view, new ViewGroup.LayoutParams(-2, -1)); 61 this.loadingDialog.setCancelable(true); 62 this.loadingDialog.show(); 63 } 64 65 private void getFoodMenuData() { 66 JuheData.executeWithAPI(mContext, 46, "http://apis.juhe.cn/cook/category", "get", null, new DataCallBack() { 67 68 @Override 69 public void onFailure(int arg0, String arg1, Throwable arg2) { 70 71 Toast.makeText(mContext, "获取菜单分类信息失败,请检查网络!", Toast.LENGTH_LONG).show(); 72 } 73 74 @Override 75 public void onFinish() { 76 loadingDialog.dismiss(); 77 78 } 79 80 @Override 81 public void onSuccess(int arg0, String arg1) { 82 save(arg1); 83 84 } 85 }); 86 87 } 88 89 public void save(String s) { 90 91 try { 92 FileOutputStream outfile = openFileOutput("current_file", Context.MODE_PRIVATE); 93 outfile.write(s.getBytes()); 94 outfile.close(); 95 // Toast.makeText(this, "保存成功", 3000).show(); 96 } catch (Exception e) { 97 // Toast.makeText(this, "保存失败", 3000).show(); 98 } 99 } 100 101 public String showData() { 102 String content = ""; 103 try { 104 FileInputStream showfile = openFileInput("current_file"); 105 ByteArrayOutputStream out = new ByteArrayOutputStream(); 106 byte[] data = new byte[1024]; 107 int len = 0; 108 109 while ((len = showfile.read(data)) != -1) { 110 out.write(data, 0, len); 111 } 112 content = new String(out.toByteArray()); 113 // Toast.makeText(this, "显示成功", 3000).show(); 114 } catch (Exception e) { 115 // Toast.makeText(this, "显示失败", 3000).show(); 116 } 117 return content; 118 } 119 120 private void initView() { 121 this.iv_back = (ImageView) findViewById(R.id.iv_back); 122 this.iv_back.setVisibility(0); 123 this.iv_back.setOnClickListener(this); 124 this.tv_title = (TextView) findViewById(R.id.tv_title); 125 this.tv_title.setText(R.string.food); 126 listView = (ExpandableListView) findViewById(R.id.expandablelist); 127 listView.setGroupIndicator(null); 128 showLoadingDialog(); 129 String info = showData(); 130 if (info.isEmpty()) { 131 getFoodMenuData(); 132 info = showData(); 133 } else { 134 FoodMenuParser parser = new FoodMenuParser(FoodActivity.this.mContext); 135 List<FirstFoodMenu> fMenus = parser.parser(info, 0); 136 if (fMenus != null) { 137 strings = new String[fMenus.size()]; 138 strings2 = new String[fMenus.size()]; 139 strings3 = new String[fMenus.size()][];// 初始化strings3[][]数组 140 for (int i = 0; i < fMenus.size(); i++) { 141 FirstFoodMenu fMenu = fMenus.get(i); 142 strings[i] = fMenu.getName(); 143 strings2[i] = fMenu.getParentId(); 144 ArrayList<SecondFoodMenu> sMenus = fMenu.getSecondFoodMenus(); 145 strings3[i] = new String[sMenus.size()]; 146 for (int j = 0; j < sMenus.size(); j++) { 147 strings3[i][j] = sMenus.get(j).getName(); 148 } 149 }loadingDialog.dismiss(); 150 } 151 adapter = new FoodMenuAdapter(mContext, strings, strings3); 152 listView.setAdapter(adapter); 153 listView.setOnGroupExpandListener(new OnGroupExpandListener() { 154 @Override 155 public void onGroupExpand(int groupPosition) { 156 // TODO Auto-generated method stub 157 for (int i = 0; i < adapter.getGroupCount(); i++) { 158 if (groupPosition != i) 159 listView.collapseGroup(i); 160 } 161 } 162 }); 163 164 } 165 } 166 167 @Override 168 public void onClick(View v) { 169 if (v.getId() == R.id.iv_back) 170 finish(); 171 } 172 173 }
布局文件就贴上来了,如果在调试代码需要可以联系我。
以上是我在实训过程中做的第二个练手小Demo,下一个练手的是在这个基础上进行扩展:通过在菜单选择某一个菜肴,点击后可以看到这个菜的做的具体步骤。
利用ExpandableListView和gridview 显示可展开折叠菜单导航
标签:
原文地址:http://www.cnblogs.com/deBug-hao/p/4745742.html