關於ListView中巢狀EditText,焦點及其他點選問題
之前專案做過這個類似的UI,處理起來也很麻煩,要求的效果是
1.EditText點擊出現輸入法,遊標顯示在最後,效果如圖
2.編輯完內容後,收起鍵盤儲存修改內容。
這裡會用到幾個類
1.自定義Adapter(主要的處理也是在這裡)
2.自定義的EditText(處理關閉輸入法)
3.網上找的監聽輸入法關閉和開啟SoftKeyboardStateHelper
ListView的Item的XML檔案
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:background="#ffffff" android:id="@+id/my_layout"> <com.example.listandeditfocus.MyEditText android:id="@+id/edit" android:layout_width="100dp" android:layout_height="wrap_content" android:text="張三" android:gravity="center" android:paddingTop="10dp" android:paddingBottom="10dp" android:background="@null" /> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="好的" app:layout_constraintStart_toEndOf="@id/edit" android:gravity="center" app:layout_constraintTop_toTopOf="@id/edit"/> </android.support.constraint.ConstraintLayout>
這裡用到的是自定義的EditText,其實就是重寫了一個方法,去處理關閉輸入法,後面會介紹,EditText巢狀在ListView中,會出現幾個問題
1.EditText遊標顯示不正常
2.EditText焦點消失
3.造成ListView的setOnItemClickListener方法設定的Listenner無效,即點選Item卻沒有響應,
下面的程式碼中會借用到一個類來監聽輸入法鍵盤的開啟和收起,這裡先介紹下
SoftKeyboardStateHelper,這個類的出處來自該類的來源地,程式碼如下
public class SoftKeyboardStateHelper implements ViewTreeObserver.OnGlobalLayoutListener { public interface SoftKeyboardStateListener { void onSoftKeyboardOpened(int keyboardHeightInPx); void onSoftKeyboardClosed(); } private final List<SoftKeyboardStateListener> listeners = new LinkedList<SoftKeyboardStateListener>(); private final View activityRootView; private int lastSoftKeyboardHeightInPx; private boolean isSoftKeyboardOpened; public SoftKeyboardStateHelper(View activityRootView) { this(activityRootView, false); } public SoftKeyboardStateHelper(View activityRootView, boolean isSoftKeyboardOpened) { this.activityRootView = activityRootView; this.isSoftKeyboardOpened = isSoftKeyboardOpened; activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this); } @Override public void onGlobalLayout() { final Rect r = new Rect(); //r will be populated with the coordinates of your view that area still visible. activityRootView.getWindowVisibleDisplayFrame(r); final int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top); if (!isSoftKeyboardOpened && heightDiff > 100) { // if more than 100 pixels, its probably a keyboard... isSoftKeyboardOpened = true; notifyOnSoftKeyboardOpened(heightDiff); } else if (isSoftKeyboardOpened && heightDiff < 200) { //這個200是我做的一個修改,實際使用的時候debug發現有時候高度不一定是小於100 我的是189,具體情況具體修改 isSoftKeyboardOpened = false; notifyOnSoftKeyboardClosed(); } } public void setIsSoftKeyboardOpened(boolean isSoftKeyboardOpened) { this.isSoftKeyboardOpened = isSoftKeyboardOpened; } public boolean isSoftKeyboardOpened() { return isSoftKeyboardOpened; } /** * Default value is zero (0) * @return last saved keyboard height in px */ public int getLastSoftKeyboardHeightInPx() { return lastSoftKeyboardHeightInPx; } public void addSoftKeyboardStateListener(SoftKeyboardStateListener listener) { listeners.add(listener); } public void removeSoftKeyboardStateListener(SoftKeyboardStateListener listener) { listeners.remove(listener); } private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx) { this.lastSoftKeyboardHeightInPx = keyboardHeightInPx; for (SoftKeyboardStateListener listener : listeners) { if (listener != null) { listener.onSoftKeyboardOpened(keyboardHeightInPx); } } } private void notifyOnSoftKeyboardClosed() { for (SoftKeyboardStateListener listener : listeners) { if (listener != null) { listener.onSoftKeyboardClosed(); } } } }
接著看下在ListView的Adapter中進行的處理
public class ListItemAdapter extends BaseAdapter implements SoftKeyboardStateHelper.SoftKeyboardStateListener { List<Integer> data = null; Context mContext = null; private String s; boolean isKeyboardOpen = false; int currentFocusPosition = -1; EditText onFocusEdit = null; public ListItemAdapter(List<Integer> data, Context context) { this.data = data; mContext = context; } @Override public int getCount() { return this.data.size(); } @Override public Integer getItem(int position) { return this.data.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); convertView = View.inflate(mContext, R.layout.item_layout, null); holder.editText = convertView.findViewById(R.id.edit); holder.layout = convertView.findViewById(R.id.my_layout); holder.textView = convertView.findViewById(R.id.tv); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } /** 通過給Item的佈局檔案的最外層的ViewGroup新增OnCLick,來響應Item的點選(解決問題3 ListView的setOnItemClickListener不響應的問題,具體為什麼不響應可以看下面的連結) */ holder.layout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mContext.startActivity(new Intent(mContext,Main2Activity.class)); } }); final ViewHolder finalHolder = holder; /** 給EditText設定FocusChangeListener,監聽焦點變化,獲取焦點的時候,將遊標設定到最後方便刪除修改 */ holder.editText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { finalHolder.editText.setSelection(finalHolder.editText.getText().length()); //儲存當前獲取到焦點的位置和控制元件物件 currentFocusPosition = position; onFocusEdit = finalHolder.editText; } else { /** 失去焦點的時候儲存當前的修改內容 */ finalHolder.editText.setText(finalHolder.editText.getText()); } } }); /** 這一步用來處理問題2,焦點消失,點選EditText後獲取到焦點, 輸入法開啟,焦點又立刻消失,這是因為輸入法鍵盤開啟會是佈局發生變化,會造成重新呼叫Adapter的getView方法, 使EditText的焦點消失,這裡我們利用一個變數currentFocusPosition記錄獲取到焦點的控制元件所處的位置, 初始值設定為-1,表示當前沒有獲得焦點的控制元件 (在上方的focusChange中記錄),判斷位置相等,重新請求獲得焦點。 !!! 注意這裡不能用記錄的獲取焦點的控制元件,即onFocusEdit來做比較,因為這裡的View存在複用, 這個EditText可能獲取的是上一個EditText的焦點 */ if (currentFocusPosition == position) { holder.editText.requestFocus(); } return convertView; } /** 下面2個回撥方法就是實現了上面的SoftKeyboardStateHelper.SoftKeyboardStateListener介面,獲取到鍵盤開啟和關閉提醒(SoftKeyboardStateHelper在Activity中通過 SoftKeyboardStateHelper softKeyboardStateHelper = new SoftKeyboardStateHelper(findViewById(R.id.main_layout));(Activity的佈局的最外層ViewGroup) softKeyboardStateHelper.addSoftKeyboardStateListener(adapter);)設定 */ @Override public void onSoftKeyboardOpened(int keyboardHeightInPx) { isKeyboardOpen = true; } @Override public void onSoftKeyboardClosed() { isKeyboardOpen = false; currentFocusPosition = -1; //當我們收到輸入法鍵盤關閉的時候,清除當前的EditText獲取到的焦點 if (onFocusEdit != null) { onFocusEdit.clearFocus(); } } class ViewHolder { EditText editText; ConstraintLayout layout; TextView textView; }
接下來是處理關閉輸入法,這個處理是在自定義的EditText中進行
public class MyEditText extends android.support.v7.widget.AppCompatEditText {
public MyEditText(Context context) {
super(context);
}
public MyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
//有的鍵盤有收起按鍵,有的沒有,所以這裡是利用手機的後退鍵關閉鍵盤
//判斷當前點選的是後退,手指擡起,而且!! 當前EditText是有焦點的,關閉輸入法,否則按照原處理方式進行
//EditText沒有焦點 很有可能鍵盤已經收起了,就不需要再次關閉鍵盤。這時候之前設定的鍵盤變化監聽就會回撥
//清除當前焦點
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP && this.isFocused()) {
InputMethodManager inputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(this.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
return true;
} else
return super.onKeyPreIme(keyCode, event);
}
}
所有處理已完成,如果大家有更好的,更簡潔高效的方法,歡迎分享和留言。一起改進處理方式
相關推薦
關於ListView中巢狀EditText,焦點及其他點選問題
之前專案做過這個類似的UI,處理起來也很麻煩,要求的效果是 1.EditText點擊出現輸入法,遊標顯示在最後,效果如圖 2.編輯完內容後,收起鍵盤儲存修改內容。 這裡會用到幾個類 1.自定義Adapter(主要的處理也是在這裡) 2.自定義的EditText(
在ListView中巢狀ViewFlow,ViewFlow滑動有些卡頓的問題~
最近做類似於網易新聞頭條那種圖片Banner,實現方法是:在ListView中巢狀ViewFlow,但是ViewFlow的滑動總是不是那麼順暢,覺得應該是觸屏事件攔截衝突的問題吧,在網上查閱了一下我的解決方法如下: 在ViewFlow中宣告mListView,然後將父ListView傳入到ViewFlow,
android ScrollView中巢狀GridView,ListView只顯示一行的解決辦法
注:本文是由網上大神分享的解決方案彙集而成 方法一: 重寫ListView、GridView: 重寫ListView: public class MyListView extends ListView { public MyListView(Context contex
ListView中巢狀GridView時GridView的資料無法完全顯示,只顯示一行
這種情況下需要自定義一個GridView,然後重寫GridView的onMeasure(int widthMeasureSpec, int heightMeasureSpec)的方法,將GridView重新測量,並且指定GridView的新的高度 package com.y
ScrollView巢狀EditText,導致EditText顯示多行時滑動失效的問題
ScrollView巢狀EditText,這會有什麼問題呢,我這裡說的是當EditText內輸入多行內容,當EditText所在佈局不夠的時候,必然需要滑動檢視輸入的所有內容。可是當我們把EditText放在ScrollView裡面的時候,會發現EditText的滑動失效了。 原因就
陣列中巢狀物件,根據物件的某個字對物件進行去重
// 陣列中巢狀物件,根據物件的某個欄位進行物件去重 function uniqObj(data, name) { var dataArr = []; var dataObj = {}; for (var i = 0; i < data.length; i+
fragment中巢狀viewpager,vierpager中有多個fragment,不顯示 ...
現在好多應用流行一種佈局。底部幾個工具欄選項,上面也有類似tab的選項。 底部用RadioGroup控制fragment的切換。以上有五個fragment。 第一個fragment,代表著首頁。首頁又是一個類似tab的fragment,使用viewpager切換著兩
在Popupwindow佈局中巢狀ScrollView,滑動內容時檢視出現反覆閃爍的問題
解決辦法: 將顯示PopupWindow的方法由showAsDropDown()改為showAtLocation() 程式碼如下 private PopupWindow popupWind
fragment中巢狀viewpager,viewpager中有多個fragment,裡面fragment沒有顯示
fragment巢狀fragment導致裡面fragment介面沒有顯示,例子如下: private void InitViewPager(View parentView) { mPag
在Fragment中巢狀Webview,第一次開啟閃屏問題
在Fragment中巢狀Webview,特別是對Activity開啟了硬體加速,在第一次開啟時會出現閃屏,或者出現下桌面後就恢復正常,第二次就不會出現。 對於這種情況很簡單,在存放Fragment的Activity中加入一行程式碼即可解決: getWindow().se
listview中巢狀viewpager的實現總結
最近在做一個專案需要在listView中巢狀viewPager作為第一項,效果如下: 上面的佈局就是一個listView,在實現過程中遇到了以下問題: 1.listView中第一項為viewPager,其他項為單獨包含兩種資料型別,導致listView佈局混亂。 2.v
fragment中巢狀viewpager,vierpager中有多個fragment,不顯示而且滑動卡頓
現在好多應用流行一種佈局。底部幾個工具欄選項,上面也有類似tab的選項。 底部用RadioGroup控制fragment的切換。以上有五個fragment。 第一個fragment,代表著首頁。首頁又是一個類似tab的fragment,使用viewpager切換著兩個fragment。 priv
Android在RecyclerView中巢狀ScrollView,解決兩者間的滑動衝突
在RecyclerView中的item中巢狀一些佈局如TextView,在這種情況下如TextView的字數很多超過所設定的佈局大小。 這樣就需要在item中加一個ScrollView可以用於使用者的滑動。 1.RecyclerView的item佈局如: <?xml
android中ListView中巢狀GridView並且把GridView當中的內容全部顯示出來的方法
程式碼如下所示: public class MyGridView extends GridView { public MyGridView(android.content.Context context, android.u
Android-ListView中巢狀(ListView)控制元件時item的點選事件不起作用的問題
解決:1、在主listview佈局檔案中的listview中新增屬性 android:focusable="false" 2、在子listview中最頂上的佈局檔案新增屬性
Listview中巢狀Checkbox的簡單解決辦法
最近專案中做了一個關於批量刪除的這樣一個操作,以前是會做的,誰知道記性不好忘光了,經過一番折騰還是完美的實現了,相信後面還有無數個和我一樣的渣渣會遇到這個問題,那麼就讓我來分享一下咯。 當然這個checkbox控制元件是寫在item佈局中的。我這邊的需求是點選編輯按鈕才會顯
ListView中巢狀GridView點選事件
做一個專案時,需要在ListView中巢狀GridView,因為ListView的每個條目中不一定出現GridView,那麼問題來了,新增GridView的Item的點選事件後,有GridView出現的條目中,ListView的Item點選事件無法觸發,這時我們就需要設定L
recyclerview巢狀GridView去遮蔽後者的點選事件,而是前者響應到事件。
無論是標題中的巢狀方式,還是其它列表控制元件之間的巢狀,都適用。 1、在GirdView的所在佈局的根佈局中設定改屬性: android:descendantFocusability="blacksDescendants" 2、動態設定GirdView的如下屬性: gridvi
ListView中Item與Item的子控制元件點選事件衝突問題解決
心靈包含人所有的一切有意識、無意識的思想、情感和行為。——《星夜心理書系》 1、問題 在Android開發時,ListView中點選一個Item,會一併觸發其子控制元件的點選事件。比如Item中的Button、ImageButton等。導致了點選
ListView中嵌入佈局的Button或多個點選事件
ListView中嵌入佈局的多個點選事件 有時候在ListView嵌入的佈局中有多個事件需要點選,比如一個item中有TextView和Button兩個佈局,當我們需要獲取這兩個點選事件時,我們應該如何去獲取呢,通常來說,我們都是已經固定好了TextVie