這篇隨身筆帶來的是結合聚合數據「菜譜大全」作的一個菜譜可摺疊一級+二級列表。java
先發來一些截圖一睹爲快吧。android
ExpandableListView 可用於摺疊型菜單列表,其佈局主要經過getGroupView和getChildView兩種的重寫來實現。在子列表項目比較多的狀況下,能夠經過GridView來佈局子列表。json
下面來講說ExpandableListView的適配器ExpandableListadapter的一些變量和方法:windows
1、首先:咱們知道ExpandableListView分爲父列表和子列表,其中 父列表經過一維數組String[]進行數據填充,子類表經過二維數組String[][]填充。api
ExpandableListadapter重要的方法:數組
public long getGroupId(int groupPosition) 根據groupPosition獲取與該組相關聯的標識網絡
public Object getGroup(int groupPosition) 獲取與在給定組相關的數據。app
public int getGroupCount() 返回Group的組數目。eclipse
getChildId (int groupPosition, int childPosition) 獲取與在給定組給予孩子相關的數據。ide
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,而且其順序和上一個參數每一項一一對應。
2、下面是我結合聚合數據中的「菜譜大全"的數據作的一個菜單導航。
一、菜單分類的獲取:
這裏省略一些過程,聚合數據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,下一個練手的是在這個基礎上進行擴展:經過在菜單選擇某一個菜餚,點擊後能夠看到這個菜的作的具體步驟。