关于ListView GridView 嵌套遇到的坑

前言

随着项目的需求及展示要求,一般ListView都会涉及到嵌套问题,本文就关于嵌套问题,集合平时开发遇到的坑,做一个介绍,祭奠我们遇到的坑!欢迎大家补充。


1.获取一个 ListView 的当前点击的 ItemView 。

public View getItemViewByPosition(int pos, AdapterView listView) {
    final int firstListItemPosition = listView.getFirstVisiblePosition();
    final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1;

    if (pos < firstListItemPosition || pos > lastListItemPosition) {
        return listView.getAdapter().getView(pos, null, listView);
    } else {
        final int childIndex = pos - firstListItemPosition;
        return listView.getChildAt(childIndex);
    }
}

这个方法,如果有坑,欢迎大家留言讨论,尤其是ListView 有 HeaderView 的时候。比较稳妥的,我是采用嵌套方法,找到我要求的 view 的parentView,如下。

2.根据当前点击的 view 获取他的 ParentView,可以代替1.

比如我需要找到 v 的父控件,或者'爷爷'控件,我们只要知道父控件的 id,比如:R.id.ll_left,R.id.ll_right。

@Override
public boolean onLongClick(View v) {
    LogUtils.d("info", "View info:" + v.toString());

    View convertView = null;

    try {
        MessageView message = (MessageView) v.getTag();
        int position = messageList.indexOf(message);

        boolean isIncoming = message.getDirection() == Direction.INCOMING;
        convertView = findLinearLayoutViewByChild(v, isIncoming);

        if (convertView != null) {
            convertView.setTag(message);
            callBack.execute(position, convertView);
        }
    } catch (Exception e) {
        LogUtils.e("info", e.toString());
    }

    return true;
}

//方法
private View findLinearLayoutViewByChild(View v, boolean inComing) {
        View viewGroup = null;
        View res = null;
        View parent = null;
        parent = (View) v.getParent();
        if (v instanceof ViewGroup) {
            viewGroup = (ViewGroup) v;

            if (inComing) {
                res = viewGroup.findViewById(R.id.ll_left);
            } else {
                res = viewGroup.findViewById(R.id.ll_right);
            }

            if (res != null) {
                return res;
            } else {
                if (parent != null) {
                    return findLinearLayoutViewByChild((View) v.getParent(), inComing);
                } else {
                    return null;
                }

            }
        } else {
            if (parent != null) {
                return findLinearLayoutViewByChild((View) v.getParent(), inComing);
            } else {
                return null;
            }
        }
    }

3.ListView Item嵌套GridView ,GridView里面的空白处的长按事件不执行的解决方案。

相信大家一看就知道怎么解决的。

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.AdapterView;
import android.widget.GridView;

public class MyGridView extends GridView {
    public MyGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyGridView(Context context) {
        super(context);
    }

    public MyGridView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }

    // 用来处理是否为长按的Runnable
    private Runnable mLongClickRunnable = new Runnable() {
        @Override
        public void run() {
            performLongClick();
        }
    };

    int downX;
    int downY;

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            downX = (int) ev.getX();
            downY = (int) ev.getY();

            // 根据按下的X,Y坐标获取所点击item的position
            int position = pointToPosition(downX, downY);

            // 点击在 item 的位置
            if (position != AdapterView.INVALID_POSITION) {
                return super.dispatchTouchEvent(ev);
            }

            // 不是itemview的位置的时候,mLongClickRunnable
            postDelayed(mLongClickRunnable, ViewConfiguration.getLongPressTimeout());
            break;

        case MotionEvent.ACTION_MOVE:
            int moveX = (int) ev.getX();
            int moveY = (int) ev.getY();

            int movePosition = pointToPosition(moveX, moveY);
            // 如果我们在按下的空白区域内移动,只要不进入有item的区域我们就不移除 mRunnable
            if (movePosition != AdapterView.INVALID_POSITION) {
                removeCallbacks(mLongClickRunnable);
            }
            
            //如果在空白区域移动过多,我们移除空白区域的 mRunnable
            if (movePosition == AdapterView.INVALID_POSITION
                    && (Math.abs(moveX -downX)>ViewConfiguration.getTouchSlop()
                            || Math.abs(moveY -downY)>ViewConfiguration.getTouchSlop())) {
                removeCallbacks(mLongClickRunnable);
            }
            break;

        case MotionEvent.ACTION_UP:
            removeCallbacks(mLongClickRunnable);
            break;
        }
        return super.dispatchTouchEvent(ev);
    }
}

你可能感兴趣的:(关于ListView GridView 嵌套遇到的坑)