android:ListView中使用EditText,遇到的坑,獲取點擊焦點、保存輸入文本的demo

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展示框,然後右邊放一個能夠編輯的輸入框,也是比較簡單的。



一個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
		}
	}

}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章