标签:android listview 联动 地区控件 多层
在日常的App开发中,尤其是在开发生活服务的应用上,很多时候,我们会需要联动地展现省市区的数据等,需求大概如下:
1)展现所有省份
2)当点击某省份的时候,在二级菜单上展现此省份下面所属的城市列表
3)选中返回,显示我们选中的城市
4)当重新进入选择页面的时候,标识出我们上一次选中(或者说当前已民选择)的值
下图是一个类似的ListView联动选择控件。
1)首先定义一个Layout,左右各放置一个ListView,大概界面如下:
2)自定义一个控件(ValuePicker),在控件中,首先我们要获取填充两个ListView的数据,如果在是省市的话,就要获取省市的数据,在这个Demo中,我们利用DataProvider这个类,来模拟一些数据,如下:
public class DataProvider { public static final String[] summaries = { "A", "B", "C", "D", "E", "F", "G", "H" }; public static final Map<String, String[]> details = new HashMap<>(); static { details.put("A",new String[] {"A1", "A2", "A3"}); details.put("B",new String[] {"B1", "B2", "B3"}); details.put("C",new String[] {"C1", "C2", "C3"}); details.put("D",new String[] {"D1", "D2", "D3"}); details.put("E",new String[] {"E1", "E2", "E3"}); details.put("F",new String[] {"F1", "F2", "F3"}); details.put("G",new String[] {"G1", "G2", "G3"}); details.put("H",new String[] {"G1", "H2", "H3"}); } }
private String[] summaries = DataProvider.summaries; private Map<String, String[]> details = DataProvider.details;
由于Android本身提供的ListView是没有选中的效果的,而基于我们的需求,
3.1)需要在用户点击Item的时候,设置Item选中的状态,在这里,我们是利用"黑底白字",反转颜色来突出显示的效果。
3.2)而当我们点击另外一个Item的时候,需要将原来的Item重新置为未选中的状态,即要重新设置其背景和字体颜色,重新变成“白底黑字”,而将当前新选中的Item置为选中。
3.3)一种特殊情况是,ListView里面的个数超出当前屏幕的话,当我们滑动ListView的时候,ListView是会复用我们之前已经创建过的View的,所以,我们必须对选中的Item做一个特殊处理。被选中的Item,如果滑出屏幕,其对应的View是会被复用的,所以必须在其被复用的时候,将其置为未选中状态,而当其重新滑入屏幕的时候,将其置为选中状态。
基于以上几种情况,我们需要在Adapter中记录下某个被选中的Item的位置和View,代码如下:
/** * the View checked */ private TextView mLastCheckedView = null; /** * the position in the data */ private int mCheckedPosition = -1; public void setCheckedPosition(int position){ mCheckedPosition = position; } ... /** * @param checkedView the checkedView to set */ public void setCheckedView(View checkedView) { setViewSelected(mLastCheckedView, false); TextView textView = (TextView)checkedView; setViewSelected(textView, true); } private void setViewSelected(TextView view, boolean selected){ if(view != null){ if(selected){ view.setBackgroundColor(mContext.getResources().getColor(R.color.black)); view.setTextColor(mContext.getResources().getColor(R.color.white)); mLastCheckedView = view; }else{ view.setBackgroundColor(mContext.getResources().getColor(R.color.white)); view.setTextColor(mContext.getResources().getColor(R.color.black)); } } }
在getView的时候,根据是否选中的位置来处理View的状态,如下:
@Override public View getView(int position, View convertView, ViewGroup root) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item_card_number, null); holder.name = (TextView) convertView.findViewById(R.id.textView1); convertView.setTag(holder); }else{ holder = (ViewHolder) convertView.getTag(); } setViewSelected(holder.name, mCheckedPosition == position); holder.name.setText(mData[position]); return convertView; }
另外,由于是联动的ListView,当左边的某个Item被点击的时候,右边的ListView要对应的刷新数据,所以Adapter也必须提供对应的入口去刷新数据。
public void setData(String[] data){ mData = data; mLastCheckedView = null; mCheckedPosition = -1; notifyDataSetChanged(); }
private int mPosLeft = -1; private String mCurLeft; private int mPosRight = -1; private String mCurRight;
以下代码为找出对应的位置。
for(int i = 0; i < len; i++){ String summary = summaries[i]; if(summary.equals(mCurLeft)){ mPosLeft = i; break; } } if(mPosLeft >= 0){ String summary = summaries[mPosLeft]; String[] right = details.get(summary); int lenOfRight = right.length; for(int j = 0; j < lenOfRight; j++){ String detail = right[j]; if(mCurRight != null && detail.equals(mCurRight)){ mPosRight = j; break; } } }
final SingleCheckedListAdapter lAdapter = new SingleCheckedListAdapter(mContext, summaries); lAdapter.setCheckedPosition(mPosLeft); lvLeft.setAdapter(lAdapter); String[] rights = new String[]{}; if(mPosLeft >= 0 && mPosRight >= 0){ rights = details.get(summaries[mPosLeft]); } final SingleCheckedListAdapter rAdapter = new SingleCheckedListAdapter(mContext, rights); rAdapter.setCheckedPosition(mPosRight); lvRight.setAdapter(rAdapter);在上面也有一点要注意的就是,当左边值有选中的时候,我们要将其对应的右边的ListView的内容也给找出来,并将其绑定到右边的ListView中。
而在OnItemClickListener中,我们就要根据我们选中的位置,重新去置这个值。
lvLeft.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View view, int position, long id) { mCurRight = null; lAdapter.setCheckedPosition(position); lAdapter.setCheckedView(view); mPosLeft = position; rAdapter.setData(details.get(summaries[mPosLeft])); } }); lvRight.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View view, int position, long id) { rAdapter.setCheckedPosition(position); rAdapter.setCheckedView(view); mCurRight = details.get(summaries[mPosLeft])[position]; } });
/** * Listener to handle the logic when current city card number is selected */ public OnClickListener mListener; /** * @param listener the listener to set */ public void setButtonOnClickListener(OnClickListener listener) { this.mListener = listener; } ... btnConfirm.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { if(mListener != null){ mListener.onClick(arg0); } } });
<com.lms.twofoldselector.ValuePicker android:id="@+id/vpTest" android:layout_width="match_parent" android:layout_height="match_parent" > </com.lms.twofoldselector.ValuePicker>
public class ValuePickerMockActivity extends Activity implements OnClickListener{ public static final String SELECTED_LEFT = "SELECTED_LEFT"; public static final String SELECTED_RIGHT = "SELECTED_RIGHT"; private ValuePicker vpTest; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_vp_mock); vpTest = (ValuePicker) findViewById(R.id.vpTest); vpTest.setButtonOnClickListener(this); //set the selected view Intent intent = getIntent(); String leftValue = intent.getStringExtra(SELECTED_LEFT); String rightValue = intent.getStringExtra(SELECTED_RIGHT); vpTest.setLeftValue(leftValue); vpTest.setRightValue(rightValue); vpTest.initialize(); } @Override public void onClick(View arg0) { String rightValue = vpTest.getRightValue(); if(rightValue == null){ Toast.makeText(this, "请选择右边的值", Toast.LENGTH_SHORT).show(); return; } Intent data = new Intent(); data.putExtra(SELECTED_LEFT, vpTest.getLeftVaue()); data.putExtra(SELECTED_RIGHT, vpTest.getRightValue()); setResult(RESULT_OK, data); finish(); } }
Android学习小Demo(21)ListView的联动选择,布布扣,bubuko.com
Android学习小Demo(21)ListView的联动选择
标签:android listview 联动 地区控件 多层
原文地址:http://blog.csdn.net/linmiansheng/article/details/37914675