最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

小心!Listview結(jié)合EditText使用實例中遇到的那些坑

 更新時間:2016年06月20日 10:48:07   作者:曾博文  
小心!Listview結(jié)合EditText使用實例中遇到的那些坑,解決EditText焦點丟失、保存數(shù)據(jù)以及滾動沖突的問題,感興趣的小伙伴們可以參考一下

前幾天一同學項目中的某個功能需要ListView+EditText來實現(xiàn),希望我給他寫個Demo,自己就隨手寫了一個小的Demo。后來想了想覺得這個功能其實挺常用的,而且期間也踩了幾個坑,就整理了一下,希望能夠幫到大家。好了,廢話不多說了,接著就貼代碼。

這里寫圖片描述

一、編寫布局文件
1.activity的布局activity_main

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:paddingBottom="@dimen/activity_vertical_margin"
 android:paddingLeft="@dimen/activity_horizontal_margin"
 android:paddingRight="@dimen/activity_horizontal_margin"
 android:paddingTop="@dimen/activity_vertical_margin"
 tools:context="com.example.mytestdemo.MainActivity" >

 <ListView 
 android:id="@+id/list_view"
 android:layout_width="match_parent"
 android:layout_height="match_parent"/>

</RelativeLayout>

只有一個ListView,所以就不多說了。
2.item的布局edittext_item

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/item_content"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:paddingTop="20dp"
 android:paddingBottom="20dp"
 android:orientation="horizontal" >
 <TextView 
 android:id="@+id/text_view"
 android:layout_width="wrap_content"
 android:layout_gravity="center_vertical"
 android:gravity="center_vertical"
 android:layout_height="50dp"/>
 <EditText 
 android:id="@+id/edit_text"
 android:layout_gravity="center_vertical"
 android:layout_marginLeft="30dp"
 android:layout_width="match_parent"
 android:layout_height="100dp"
 android:gravity="top"
 android:padding="5dp"
 android:background="@drawable/shape_edittext"/>

</LinearLayout>

一個水平的LinearLayout,里面有一個TextView和一個EditText。
為了稍微好看那么一點,所以給EditText加了一個圓角矩形背景。

3.EditText的圓角矩形背景shape_edittext

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
 <solid android:color="#FFFFFFFF"/>
 <stroke android:width="1dp"
 android:color="#000000"/>
 <corners android:radius="5dp"/>
</shape>

OK,布局代碼已經(jīng)貼完了,接下來就看看咱們的邏輯代碼吧。

二、編寫MainActivity類

public class MainActivity extends Activity {
 private static final String TAG = "zbw";
 private static final int DATA_CAPACITY = 20;

 private ListView mListView;
 private List<String> mList = new ArrayList<String>(DATA_CAPACITY);
 private MyAdapter mAdapter;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 mListView = (ListView) findViewById(R.id.list_view);

 //填充數(shù)據(jù)
 for(int i = 0; i < DATA_CAPACITY; i++) {
 mList.add("" + i);
 }

 //設(shè)置Adapter
 mAdapter = new MyAdapter(this, mList);
 mListView.setAdapter(mAdapter);
 }
}

可以看到MainActivity的代碼邏輯頁比較簡單,主要操作就是生成了一個長度為20的List,然后將其作為數(shù)據(jù)源扔進Adapter里面。好了,接下來就讓我們一起來看一下最后的Adapter類。

三、編寫MyAdapter類
好了,終于到了重頭戲,接下來咱們就一步步的編寫Adapter來解決ListView和EditText的各種沖突。
1.最普通的Adapter
首先咱們先按照以往的經(jīng)驗寫一個最普通的Adapter,看一下會出現(xiàn)哪些問題:

public class MyAdapter extends BaseAdapter {
 private ViewHolder mViewHolder;
 private LayoutInflater mLayoutInflater;
 private List<String> mList;

 public MyAdapter(Context context, List<String> list) {
 mLayoutInflater = LayoutInflater.from(context);
 mList = list;
 }

 @Override
 public int getCount() {
 return mList.size();
 }

 @Override
 public Object getItem(int position) {
 return mList.get(position);
 }

 @Override
 public long getItemId(int position) {
 return position;
 }

 @Override
 public View getView(final int position, View convertView, ViewGroup parent) {
 if (convertView == null) {
 mViewHolder = new ViewHolder();
 convertView = mLayoutInflater.inflate(R.layout.edittext_item, null);
 mViewHolder.mTextView = (TextView) convertView.findViewById(R.id.text_view);
 mViewHolder.mEditText = (EditText) convertView.findViewById(R.id.edit_text);
 convertView.setTag(mViewHolder);
 } else {
 mViewHolder = (ViewHolder) convertView.getTag();
 }

 if (position <= 9) {
 mViewHolder.mTextView.setText("0" + (position));
 } else {
 mViewHolder.mTextView.setText("" + (position));
 }
 mViewHolder.mEditText.setText(mList.get(position));
 return convertView;
 }

 static final class ViewHolder {
 TextView mTextView;
 EditText mEditText;
 }
}

代碼如上,相信大家都寫過無數(shù)遍這樣類似的代碼,讓我們一起看一下這段代碼會出什么問題。運行效果如圖所示:

這里寫圖片描述

操作a:點擊“0”,光標定位到“0”,彈出軟鍵盤,“0”處的光標丟失;
操作b:再次點擊“0”,光標重新定位到“0”;
之后我又重復了一遍此步驟,不過點擊的是“1”的位置。
那么為什么會出現(xiàn)這種效果呢?點擊“0”的時候大家看的可能不是太明顯,但點擊“1”的時候大家應該能明顯看出來ListView移動了一下。沒錯,正如大家所知道的那樣,軟鍵盤彈出的時候會重新繪制界面,因此ListView進行了一次重新繪制,重新走了一邊getView方法,生成了一個新的EditText,而之前展示光標的EditText被銷毀,所以才造成了EditText的焦點丟失。既然我們已經(jīng)知道了這個問題的原因,那么接下來我們就來解決掉它吧。

2.解決焦點丟失的問題
解決思路:既然焦點丟失是因為ListView的重繪導致的,那我們就可以定義一個變量mTouchItemPosition來記錄用戶觸碰的EditText的位置,然后在getView方法中去判斷當前的position是否和用戶觸碰的位置相等,如果相等則讓其獲得焦點,否則清除焦點。而mTouchItemPosition的值可以在EditText的OnTouch事件中獲取。
代碼實現(xiàn):

 //定義成員變量mTouchItemPosition,用來記錄手指觸摸的EditText的位置
 private int mTouchItemPosition = -1;
 ...
 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
 if (convertView == null) {
 mViewHolder = new ViewHolder();
 convertView = mLayoutInflater.inflate(R.layout.edittext_item, null);
 mViewHolder.mTextView = (TextView) convertView.findViewById(R.id.text_view);
 mViewHolder.mEditText = (EditText) convertView.findViewById(R.id.edit_text);

 mViewHolder.mEditText.setOnTouchListener(new OnTouchListener() {
 @Override
 public boolean onTouch(View view, MotionEvent event) {
  //注意,此處必須使用getTag的方式,不能將position定義為final,寫成mTouchItemPosition = position
  mTouchItemPosition = (Integer) view.getTag();
  return false;
 }
 });

 convertView.setTag(mViewHolder);
 } else {
 mViewHolder = (ViewHolder) convertView.getTag();
 }

 if (position <= 9) {
 mViewHolder.mTextView.setText("0" + (position));
 } else {
 mViewHolder.mTextView.setText("" + (position));
 }
 mViewHolder.mEditText.setText(mList.get(position));

 mViewHolder.mEditText.setTag(position);

 if (mTouchItemPosition == position) {
 mViewHolder.mEditText.requestFocus();
 mViewHolder.mEditText.setSelection(mViewHolder.mEditText.getText().length());
 } else {
 mViewHolder.mEditText.clearFocus();
 }

 return convertView;
 }

讓我們重新運行看一下效果:

這里寫圖片描述

可以看到焦點丟失這個問題已經(jīng)被我們解決了。接下來就讓我們給EditText增加保存數(shù)據(jù)的功能。

3.添加保存數(shù)據(jù)的功能
首先讓我們來分析一下怎么保存EditText中的數(shù)據(jù)。其實保存數(shù)據(jù)比較簡單,我們只需要做兩步就可以了,第一步我們需要拿到EditText變化之后的數(shù)據(jù);第二步我們將這些數(shù)據(jù)替換掉之前的就大功告成了。
讓我們再次對MyAdapter類進行修改,而用于TextWatcher的afterTextChanged方法中獲取不到當前position,所以我們需要新建一個內(nèi)部類MyTextWatcher實現(xiàn)TextWatcher接口并持有一個position,其次在ViewHolder中需要持有一個MyTextWatcher的引用來動態(tài)更新其position的值,代碼如下:

@Override
 public View getView(int position, View convertView, ViewGroup parent) {
 if (convertView == null) {
 mViewHolder = new ViewHolder();
 convertView = mLayoutInflater.inflate(R.layout.edittext_item, null);
 mViewHolder.mTextView = (TextView) convertView.findViewById(R.id.text_view);
 mViewHolder.mEditText = (EditText) convertView.findViewById(R.id.edit_text);

 mViewHolder.mEditText.setOnTouchListener(new OnTouchListener() {

 @Override
 public boolean onTouch(View view, MotionEvent event) {
  //注意,此處必須使用getTag的方式,不能將position定義為final,寫成mTouchItemPosition = position
  mTouchItemPosition = (Integer) view.getTag();
  return false;
 }
 });

 // 讓ViewHolder持有一個TextWathcer,動態(tài)更新position來防治數(shù)據(jù)錯亂;不能將position定義成final直接使用,必須動態(tài)更新
 mViewHolder.mTextWatcher = new MyTextWatcher();
 mViewHolder.mEditText.addTextChangedListener(mViewHolder.mTextWatcher);
 mViewHolder.updatePosition(position);

 convertView.setTag(mViewHolder);
 } else {
 mViewHolder = (ViewHolder) convertView.getTag();
 //動態(tài)更新TextWathcer的position
 mViewHolder.updatePosition(position);
 }

 if (position <= 9) {
 mViewHolder.mTextView.setText("0" + (position));
 } else {
 mViewHolder.mTextView.setText("" + (position));
 }
 mViewHolder.mEditText.setText(mList.get(position));

 mViewHolder.mEditText.setTag(position);

 if (mTouchItemPosition == position) {
 mViewHolder.mEditText.requestFocus();
 mViewHolder.mEditText.setSelection(mViewHolder.mEditText.getText().length());
 } else {
 mViewHolder.mEditText.clearFocus();
 }

 return convertView;
 }

 static final class ViewHolder {
 TextView mTextView;
 EditText mEditText;
 MyTextWatcher mTextWatcher;

 //動態(tài)更新TextWathcer的position
 public void updatePosition(int position) {
 mTextWatcher.updatePosition(position);
 }
 }


 class MyTextWatcher implements TextWatcher {
 //由于TextWatcher的afterTextChanged中拿不到對應的position值,所以自己創(chuàng)建一個子類
 private int mPosition;

 public void updatePosition(int position) {
 mPosition = position;
 }

 @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) {
 mList.set(mPosition, s.toString());
 }
 };

現(xiàn)在保存數(shù)據(jù)的問題也已經(jīng)完成了,接下來讓我們看最后一個滾動沖突的問題。

4.解決滾動沖突的問題
其實這個問題我在完美解決EditText和ScrollView的滾動沖突(上)完美解決EditText和ScrollView的滾動沖突(下)這兩篇博客中詳細的講過,原理都是一樣的,所以這兒就不多說了,直接將原來的代碼拷過來就可以了。感興趣的同學可以去看一下之前的兩篇。

@Override
 public View getView(int position, View convertView, ViewGroup parent) {
 if (convertView == null) {
 mViewHolder = new ViewHolder();
 convertView = mLayoutInflater.inflate(R.layout.edittext_item, null);
 mViewHolder.mTextView = (TextView) convertView.findViewById(R.id.text_view);
 mViewHolder.mEditText = (EditText) convertView.findViewById(R.id.edit_text);

 mViewHolder.mEditText.setOnTouchListener(new OnTouchListener() {

 @Override
 public boolean onTouch(View view, MotionEvent event) {
  //注意,此處必須使用getTag的方式,不能將position定義為final,寫成mTouchItemPosition = position
  mTouchItemPosition = (Integer) view.getTag();

  //觸摸的是EditText并且當前EditText可以滾動則將事件交給EditText處理;否則將事件交由其父類處理
  if ((view.getId() == R.id.edit_text && canVerticalScroll((EditText)view))) {
  view.getParent().requestDisallowInterceptTouchEvent(true);
  if (event.getAction() == MotionEvent.ACTION_UP) {
  view.getParent().requestDisallowInterceptTouchEvent(false);
  }
  }
  return false;
 }
 });

 // 讓ViewHolder持有一個TextWathcer,動態(tài)更新position來防治數(shù)據(jù)錯亂;不能將position定義成final直接使用,必須動態(tài)更新
 mViewHolder.mTextWatcher = new MyTextWatcher();
 mViewHolder.mEditText.addTextChangedListener(mViewHolder.mTextWatcher);
 mViewHolder.updatePosition(position);

 convertView.setTag(mViewHolder);
 } else {
 mViewHolder = (ViewHolder) convertView.getTag();
 //動態(tài)更新TextWathcer的position
 mViewHolder.updatePosition(position);
 }

 if (position <= 9) {
 mViewHolder.mTextView.setText("0" + (position));
 } else {
 mViewHolder.mTextView.setText("" + (position));
 }
 mViewHolder.mEditText.setText(mList.get(position));

 mViewHolder.mEditText.setTag(position);

 if (mTouchItemPosition == position) {
 mViewHolder.mEditText.requestFocus();
 mViewHolder.mEditText.setSelection(mViewHolder.mEditText.getText().length());
 } else {
 mViewHolder.mEditText.clearFocus();
 }

 return convertView;
 }

 /**
 * EditText豎直方向是否可以滾動
 * @param editText 需要判斷的EditText
 * @return true:可以滾動 false:不可以滾動
 */
 private boolean canVerticalScroll(EditText editText) {
 //滾動的距離
 int scrollY = editText.getScrollY();
 //控件內(nèi)容的總高度
 int scrollRange = editText.getLayout().getHeight();
 //控件實際顯示的高度
 int scrollExtent = editText.getHeight() - editText.getCompoundPaddingTop() -editText.getCompoundPaddingBottom();
 //控件內(nèi)容總高度與實際顯示高度的差值
 int scrollDifference = scrollRange - scrollExtent;

 if(scrollDifference == 0) {
 return false;
 }

 return (scrollY > 0) || (scrollY < scrollDifference - 1);
 }

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android中子線程和UI線程通信詳解

    Android中子線程和UI線程通信詳解

    這篇文章主要介紹了Android中子線程和UI線程通信詳解,本文講解了一些概念、使用、及代碼實例,需要的朋友可以參考下
    2015-06-06
  • Android基于Http協(xié)議實現(xiàn)文件上傳功能的方法

    Android基于Http協(xié)議實現(xiàn)文件上傳功能的方法

    這篇文章主要介紹了Android基于Http協(xié)議實現(xiàn)文件上傳功能的方法,結(jié)合實例形式分析了Android的HTTP協(xié)議原理與文件上傳功能實現(xiàn)技巧,需要的朋友可以參考下
    2016-07-07
  • Kotlin淺析延遲初始化與密封類的實現(xiàn)方法

    Kotlin淺析延遲初始化與密封類的實現(xiàn)方法

    Kotlin語言的許多特性,包括變量不可變,變量不可為空,等等。這些特性都是為了盡可能地保證程序安全而設(shè)計的,但是有些時候這些特性也會在編碼時給我們帶來不少的麻煩,下面我們來了解延遲初始化和密封類的特點
    2022-08-08
  • Android中Gallery和ImageSwitcher的使用實例

    Android中Gallery和ImageSwitcher的使用實例

    今天小編就為大家分享一篇關(guān)于Android中Gallery和ImageSwitcher的使用實例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • Android Studio實現(xiàn)幀動畫

    Android Studio實現(xiàn)幀動畫

    這篇文章主要為大家詳細介紹了Android Studio實現(xiàn)幀動畫,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Android實現(xiàn)自定義的衛(wèi)星式菜單(弧形菜單)詳解

    Android實現(xiàn)自定義的衛(wèi)星式菜單(弧形菜單)詳解

    相信大家經(jīng)常在應用中會看到衛(wèi)星菜單,那么這篇文章就來介紹在Android中如何實現(xiàn)自定義的衛(wèi)星式菜單(弧形菜單),有需要的可以參考學習。
    2016-08-08
  • Android中實現(xiàn)毛玻璃效果的3種方法

    Android中實現(xiàn)毛玻璃效果的3種方法

    這篇文章主要介紹了Android中實現(xiàn)毛玻璃效果的3種方法,本文講解了使用系統(tǒng)提供的方法、自定義的方法、C語言實現(xiàn)方法等3種方法,需要的朋友可以參考下
    2015-04-04
  • Android Studio打包.so庫到apk中實例詳解

    Android Studio打包.so庫到apk中實例詳解

    這篇文章主要介紹了Android Studio打包.so庫到apk中實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • Android方向傳感器的使用方法

    Android方向傳感器的使用方法

    這篇文章主要介紹了Android方向傳感器的使用方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-10-10
  • Android實現(xiàn)可收縮和擴展的TextView

    Android實現(xiàn)可收縮和擴展的TextView

    這篇文章主要為大家詳細介紹了Android實現(xiàn)可收縮和擴展的TextView,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03

最新評論

宜春市| 湄潭县| 弋阳县| 花莲市| 锡林郭勒盟| 河南省| 石城县| 竹山县| 年辖:市辖区| 黑山县| 上林县| 朔州市| 乌鲁木齐县| 仙居县| 新津县| 宝坻区| 察雅县| 许昌市| 马龙县| 砚山县| 虞城县| 镶黄旗| 唐山市| 宜阳县| 葫芦岛市| 平舆县| 昂仁县| 新田县| 嵊泗县| 阿拉善左旗| 杂多县| 灵台县| 大方县| 合作市| 微博| 客服| 渝中区| 九龙城区| 喜德县| 铜梁县| 宁德市|