ListView一般是展示圖標、文字,用戶點擊Item後,觸發某些事件響應,很少會使用EditText,剛使用了下,發現還是有一點小坑的,記錄下來,防止以後再踩坑裏。
具體的解釋後面看看是不是需要補上,暫時把帶有註釋的完整代碼放上,保證能夠直接跑起來就好。
效果圖如下:
首先activity裏面的佈局如下activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
上面只是展示一個ListView,match_parent,這裏沒的說,比較簡單。
然後是ListView中,每一個Item的佈局my_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@+id/my_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="image_desc"/>
<TextView
android:id="@+id/my_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="10dip" />
<EditText
android:id="@+id/my_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginRight="10dip"
android:hint="input what you want" >
</EditText>
</LinearLayout>
一個Item中,包含圖片、Textview,EditText,放到一個類中來存儲,MyItem.java定義如下:
package com.example.mylistview;
public class MyItem {
private int imageId;//圖片展示
private String descItem;//item描述
private String editItem;//item編輯框
public MyItem(int id,String desc){
imageId=id;
descItem=desc;
}
public int getImageId() {
return imageId;
}
public void setImageId(int imageId) {
this.imageId = imageId;
}
public String getDescItem() {
return descItem;
}
public void setDescItem(String descItem) {
this.descItem = descItem;
}
public String getEditItem() {
return editItem;
}
public void setEditItem(String editItem) {
this.editItem = editItem;
}
}
上面這個類,也是簡單的很,上述的這些,都是最最簡單的基礎定義,下面是核心的adapter、activity。
首先是MainActivity.java文件
package com.example.mylistview;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MainActivity extends Activity {
private List<MyItem> itemList = new ArrayList<MyItem>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//加載佈局文件
initMyItems();//初始化List
// 自定義或者原有的適配器,其參數都是:上下文,佈局ID,範型列表list
MyAdapter adapter = new MyAdapter(MainActivity.this, R.layout.my_item,
itemList);
ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);//渲染展示adapter內容
}
public void initMyItems() {
MyItem a = new MyItem(R.drawable.ic_launcher, "a_item");
itemList.add(a);
MyItem b = new MyItem(R.drawable.ic_launcher, "b_item");
itemList.add(b);
MyItem c = new MyItem(R.drawable.ic_launcher, "c_item");
itemList.add(c);
MyItem d = new MyItem(R.drawable.ic_launcher, "d_item");
itemList.add(d);
MyItem e = new MyItem(R.drawable.ic_launcher, "e_item");
itemList.add(e);
MyItem f = new MyItem(R.drawable.ic_launcher, "f_item");
itemList.add(f);
MyItem g = new MyItem(R.drawable.ic_launcher, "g_item");
itemList.add(g);
MyItem h = new MyItem(R.drawable.ic_launcher, "h_item");
itemList.add(h);
MyItem i = new MyItem(R.drawable.ic_launcher, "i_item");
itemList.add(i);
MyItem j = new MyItem(R.drawable.ic_launcher, "j_item");
itemList.add(j);
MyItem k = new MyItem(R.drawable.ic_launcher, "k_item");
itemList.add(k);
MyItem l = new MyItem(R.drawable.ic_launcher, "l_item");
itemList.add(l);
MyItem m = new MyItem(R.drawable.ic_launcher, "m_item");
itemList.add(m);
MyItem n = new MyItem(R.drawable.ic_launcher, "n_item");
itemList.add(n);
MyItem o = new MyItem(R.drawable.ic_launcher, "o_item");
itemList.add(o);
MyItem p = new MyItem(R.drawable.ic_launcher, "p_item");
itemList.add(p);
MyItem q = new MyItem(R.drawable.ic_launcher, "q_item");
itemList.add(q);
MyItem r = new MyItem(R.drawable.ic_launcher, "r_item");
itemList.add(r);
MyItem s = new MyItem(R.drawable.ic_launcher, "s_item");
itemList.add(s);
}
}
下面是MyAdapter.java的內容
package com.example.mylistview;
import java.util.List;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnTouchListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
public class MyAdapter extends ArrayAdapter<MyItem> {
// 佈局ID
private int resourceId;
// 點擊過的item,用於焦點獲取
private int touchItemPosition = -1;
// 參數:上下文,佈局ID,範型列表
public MyAdapter(Context context, int textViewResourceId,
List<MyItem> objects) {
super(context, textViewResourceId, objects);
// 第二個參數很重要,是listview中每一個item的佈局
resourceId = textViewResourceId;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 通過position,來獲取當前的範型,也就是MyItem,爲的是獲取內容,得到傳遞到adapter中的MyItem數組中的一個
MyItem myItem = getItem(position);
View view;
ViewHolder viewHolder;
// 參數convertView其實時用來緩存View的,如果曾經加載過當前position的View,會緩存下來的,無需每次都去獲取新的佈局
// 該參數用於將之前加載好的佈局進行緩存,便於之後進行重用
if (convertView == null) {
// 通過LayoutInflater來加載傳遞到適配器中的佈局,也就是每一項item包括什麼東西
view = LayoutInflater.from(getContext()).inflate(resourceId, null);
// 除了佈局可以緩存處理,還可以將佈局中的控件進行緩存處理,viewHolder就是用於緩存的
viewHolder = new ViewHolder();
viewHolder.my_image = (ImageView) view.findViewById(R.id.my_image);
viewHolder.my_desc = (TextView) view.findViewById(R.id.my_desc);
viewHolder.my_edit = (EditText) view.findViewById(R.id.my_edit);
// 設置點擊的監聽,用於獲取用戶點擊的是第幾個item
viewHolder.my_edit.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
touchItemPosition = (Integer) view.getTag();
return false;
}
});
viewHolder.myTextWatcher = new MyTextWatcher();
viewHolder.my_edit.addTextChangedListener(viewHolder.myTextWatcher);
viewHolder.updatePosition(position);
// 把查找的view緩存起來方便多次重用
view.setTag(viewHolder);
} else {
view = convertView;
viewHolder = (ViewHolder) view.getTag();
viewHolder.updatePosition(position);//這行非常重要,如果不加,會導致輸入到底X行,卻展示到了Y行的輸入框,也就是無論是初次設置View還是使用緩存的View,都要重新更新position信息
}
// 向當前的view裏面,塞入數據
viewHolder.my_image.setImageResource(myItem.getImageId());
viewHolder.my_desc.setText(myItem.getDescItem());
viewHolder.my_edit.setText(myItem.getEditItem());
// 將當前的position放到中,再EditText的touch響應事件中,取出來,賦值給touchItemPosition
// 也就是,用戶點擊輸入框時,需要獲取點擊的第幾個item的框,怎麼獲取,從tag取出來,誰放進去,初始化的時候,這裏放進去
viewHolder.my_edit.setTag(position);
// 默認是-1,肯定不等於,無需有焦點,當點擊過輸入框時,會進行賦值說明用戶點擊的是第幾個,這時候會調用清除焦點,
// 然後喚起鍵盤,頁面刷新時,每一個Item都刷新,就會重新進來,而touchItemPosition有值,就會執行下面的請求焦點的代碼
if (touchItemPosition == position) {
viewHolder.my_edit.requestFocus();
viewHolder.my_edit.setSelection(viewHolder.my_edit.getText()
.length());
} else {
viewHolder.my_edit.clearFocus();
}
return view;
}
static final class ViewHolder {
ImageView my_image;
TextView my_desc;
EditText my_edit;
MyTextWatcher myTextWatcher;
public void updatePosition(int myPosition) {
myTextWatcher.updateWatcherPosition(myPosition);
}
}
class MyTextWatcher implements TextWatcher {
private int currentPosition;
public void updateWatcherPosition(int myPosition) {
currentPosition = myPosition;
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
MyItem myItem = getItem(currentPosition);
myItem.setEditItem(s.toString());//每次變化,設置對應的類的editItem
}
}
}