Listview 包含 edittext 的解决方案

时间:2024-11-15 13:05:07

转载:https://blog.****.net/qq_28268507/article/details/53666576


一、

前几天在群里聊天,碰到一个哥们问listview的itemview中包含editext时怎么处理,当初没有做过这种需求本以为很简单,结果尼玛,心酸啊…一枚小菜鸡轻轻的路过~~~嘎嘎

二、

Demo效果图:

Listview  包含 edittext 的解决方案

(android studio截图一直是这么大,很纠结,讲究着看吧….)

三、

主要解决问题点:

1.在listview中editetext焦点的问题 
2.某些机型下,点击edittext软键盘弹出紧接着又闪退问题 
3.Listview复用机制导致editext内容错乱问题

带着这些疑问,我们开始动手实践吧。

① 在listview中editetext焦点的问题?

这个问题我们需要在xml布局中给listview设置一个descendantFocusability属性,这个 属性一共有三个值beforeDescendants、afterDescendants、blocksDescendants。

beforeDescendants:viewgroup会优先其子类控件而获取到焦点 
afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点 
blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

这里我们给listview设置descendantFocusability属性为beforeDescendants,当然也可以在itemview布局的xml中为其editetext设置descendantFocusability属性为blocksDescendants,两种方式,效果都是一样的,我这里设置在了listview上;

<?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"
android:orientation="vertical"> <ListView
android:id="@+id/listview"
android:descendantFocusability="beforeDescendants"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
</LinearLayout>

② 某些机型下,点击edittext软键盘弹出紧接着又闪退问题?

我们知道安卓中软件盘弹出会导致窗口大小重新调整,所以在listview包含edttext的时候就会导致点击edittext软件盘弹出然后迅速就关闭了,我试了下某些机型下会出现问题。

这个问题也好解决,我们在清单文件对应的activity中配置下就可以解决了,最好在设置下configChanges这个属性,意思是说activity不会因为屏幕朝向改变而重新走生命周期;

<activity
android:configChanges="orientation|keyboard|keyboardHidden"
android:windowSoftInputMode="adjustPan"
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

android:windowSoftInputMode

活动的主窗口如何与包含屏幕上的软键盘窗口交互。这个属性的设置将会影响两件事情: 
1> 软键盘的状态——是否它是隐藏或显示——当活动(Activity)成为用户关注的焦点。 
2> 活动的主窗口调整——是否减少活动主窗口大小以便腾出空间放软键盘或是否当活动窗口的部分被软键盘覆盖时它的内容的当前焦点是可见的。

它的设置必须是下面列表中的一个值,或一个”state…”值加一个”adjust…”值的组合。在任一组设置多个值——多个”state…”values,例如&mdash有未定义的结果。各个值之间用|分开。

例如: <activity android:windowSoftInputMode="stateVisible|adjustResize" . . . >

在这设置的值(除”stateUnspecified”和”adjustUnspecified”以外)将覆盖在主题中设置的值 
值描述

“stateUnspecified” 软键盘的状态(是否它是隐藏或可见)没有被指定。系统将选择一个合适的状态或依赖于主题的设置。这个是为了软件盘行为默认的设置。

“stateUnchanged” 软键盘被保持无论它上次是什么状态,是否可见或隐藏,当主窗口出现在前面时。

“stateHidden” 当用户选择该Activity时,软键盘被隐藏——也就是,当用户确定导航到该Activity时,而不是返回到它由于离开另一个Activity。

“stateAlwaysHidden” 软键盘总是被隐藏的,当该Activity主窗口获取焦点时。

“stateVisible” 软键盘是可见的,当那个是正常合适的时(当用户导航到Activity主窗口时)。

“stateAlwaysVisible” 当用户选择这个Activity时,软键盘是可见的——也就是,也就是,当用户确定导航到该Activity时,而不是返回到它由于离开另一个Activity。

“adjustUnspecified” 它不被指定是否该Activity主窗口调整大小以便留出软键盘的空间,或是否窗口上的内容得到屏幕上当前的焦点是可见的。系统将自动选择这些模式中一种主要依赖于是否窗口的内容有任何布局视图能够滚动他们的内容。如果有这样的一个视图,这个窗口将调整大小,这样的假设可以使滚动窗口的内容在一个较小的区域中可见的。这个是主窗口默认的行为设置。

“adjustResize” 该Activity主窗口总是被调整屏幕的大小以便留出软键盘的空间。

“adjustPan” 该Activity主窗口并不调整屏幕的大小以便留出软键盘的空间。相反,当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分。这个通常是不期望比调整大小,因为用户可能关闭软键盘以便获得与被覆盖内容的交互操作。

③ Listview复用机制导致editext内容错乱问题?

这个问题导致的原因就是listview复用机制造成的,而我们的解决方式就是利用一个map去保存每个edittext的内容,然后在getview的时候在从map中取出来,如果有就赋值,否则置空。

完整代码如下:

package com.myapplication.test.adapter;

import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.TextView;
import com.myapplication.R;
import java.util.HashMap; /**
* 项目名称 MyApplication
* 创建时间 2016/12/14
* TODO xxxx
* Author mi
*/ public class ListViewEditeAdapter extends BaseAdapter { public HashMap<Integer, String> contents = new HashMap<>(); public ListViewEditeAdapter() {
} @Override
public int getCount() {
return 10;
} @Override
public Object getItem(int i) {
return null;
} @Override
public long getItemId(int i) {
return 0;
} @Override
public View getView(int i, View view, ViewGroup viewGroup) { ListviewEditViewHolder holder = null;
if (view == null) {
holder = new ListviewEditViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.listview_edit_item_layout, viewGroup, false));
view = holder.itemView;
view.setTag(holder);
holder.edt.addTextChangedListener(new MyTextChangedListener(holder,contents)); //尽可能减少new 新对象出来
} else {
holder = (ListviewEditViewHolder) view.getTag();
} holder.edt.setTag(i);//注意设置position if (!TextUtils.isEmpty(contents.get(i))) {//不为空的时候 赋值给对应的edittext
holder.edt.setText(contents.get(i));
} else {//置空
holder.edt.getEditableText().clear();
}
return view;
} public class MyTextChangedListener implements TextWatcher{ public ListviewEditViewHolder holder;
public HashMap<Integer, String> contents; public MyTextChangedListener(ListviewEditViewHolder holder,HashMap<Integer, String> contents){
this.holder = holder;
this.contents = contents;
} @Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override
public void afterTextChanged(Editable editable) {
if(holder != null && contents != null){
int position = (int) holder.edt.getTag();
contents.put(position,editable.toString());
}
}
} public static class ListviewEditViewHolder { public View itemView;
public TextView tv;
public EditText edt; public ListviewEditViewHolder(View v) {
itemView = v;
tv = (TextView) v.findViewById(R.id.tv);
edt = (EditText) v.findViewById(R.id.edittext);
}
} }

这里需要注意,必须要设置tag啊,不然还是会出现混乱。

在次感谢祥哥,博客地址 http://blog.****.net/u014452224?viewmode=contents 
O(∩_∩)O