[Android]在ListView嵌套GridView中出現的點擊事件處理以及gridview顯示
[Android]在ListView嵌套GridView中出現的點擊事件處理以及gridview顯示不全的問題
寫這篇博文也是出于偶然看到自己很久以前寫的一堆“爛碼”,目的是為了實現一個ListView中能夠嵌入GridView的功能,為了展示圖文的一個Item,這是一個很普通的功能,但在那時候什么都不懂的我還在自己摸索摔了很多跟頭,現在看看確實難堪,而且還有有很多的bug,所以就想挑出一兩個解決一下,為了一些像當年我一般的小伙伴提供可行性高的解決方式,特地寫了這篇整理性質的博文。(高手就不必看了)
就是想實現類似這個效果。(因為的demo,不要關注好不好看了)
那先講講主要出現的幾個問題吧:
1.listview出現點擊控件無效的情況,onItemClick事件無響應的情況,再自定義item的視圖的過程中加入了gridview、checkbox、imageButton等控件,然后就可能出現這種無法觸發onItemClickListener的問題。
我的解決方法是 在自己定義的item的布局最外層的layout 加入 這個標簽 android:descendantFocusability="blocksDescendants",就可以點擊了,這是什么意思呢?就好像是把布局中所有搶viewgroup焦點的控件全部覆蓋了先,意味著這個自定義布局就不會受其中的子控件的影響而失去點擊時間吧,我是這么想的。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@color/white" android:descendantFocusability="blocksDescendants" android:orientation="vertical" > ...........
2.在嵌套gridview的時候,gridview只顯示一行的問題。在使用中發現這個問題,然后試著指定gridview的height,發現他盡然只顯示一行,我認為這是因為嵌套的外層listview是具有scroll的功能,以至于listview不關注內部控件,如gridview的高度,并不會去自增長gridview的高度,所以解決方法很簡單,就是我們必須重寫gridview的onMeasue()方法了。
我是這么做的先繼承Gridvewi,然后重寫onMeasure.如下代碼:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); }
3.嵌套了GridView之后,發現無圖的空白區域里面沒有觸發點擊事件,既不能觸發girdview的onItemClick,也不觸發Listview的onItemClick怎么回事呢,后來發現,原來可以自己去監聽GridView的無效區域的觸發事件的。
下面是我實現的gridview代碼:
package com.example.testlistview; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.GridView; public class MyGridView extends GridView { private OnTouchInvalidPositionListener onTouchInvalidPositionListener; public MyGridView(Context context) { super(context); } public MyGridView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } @Override public boolean onTouchEvent(MotionEvent ev) { //先創建一個監聽接口,一旦點擊了無效區域,便實現onTouchInvalidPosition方法,返回true or false來確認是否消費了這個事件 if(onTouchInvalidPositionListener!=null){ if(!isEnabled()){ return isClickable()||isLongClickable(); } int motionPosition = pointToPosition((int)ev.getX(), (int)ev.getY()); if(ev.getAction()==MotionEvent.ACTION_UP&&motionPosition == INVALID_POSITION){ super.onTouchEvent(ev); return onTouchInvalidPositionListener.onTouchInvalidPosition(motionPosition); } } return super.onTouchEvent(ev); } public void setOnTouchInvalidPositionListener( OnTouchInvalidPositionListener onTouchInvalidPositionListener) { this.onTouchInvalidPositionListener = onTouchInvalidPositionListener; } public interface OnTouchInvalidPositionListener{ public boolean onTouchInvalidPosition(int motionEvent); } }