您的位置:首页 > 移动开发 > Android开发

android:ListView中使用EditText,遇到的坑,获取点击焦点、保存输入文本的demo

2017-03-07 15:41 621 查看
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
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐