前言
随着项目的需求及展示要求,一般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);
}
}