我有一个自定义 View ,扩展 RelativeLayout
并将其用作 ListView
中的列表项。它基本上是一个矩形,左侧有一个时髦的角度。根据我在 onTouchEvent
中返回的内容,我最终可能会处于两种可能的状态:
- 列表项将正确显示其按下状态并返回到未按下状态,但不会将点击发送到 ListView。
- 列表项将保持按下状态(并且无法退出),但会将点击完美地发送到 ListView。
我以前从未做过这种类型的自定义 View ,但非常感谢您的建议。我认为我错过了一些简单的东西,但我已经在这一点上花费了太多时间,无法在不问问题的情况下继续!
代码如下:
public class ListItemBackgroundView extends RelativeLayout {
private final Path PATH = new Path();
private final Paint BRUSH = new Paint(Paint.ANTI_ALIAS_FLAG);
private static int mBackgroundColor = -1;
private static int mPressedBackgroundColor = -1;
private static int mAngleOffset = -1;
private boolean isPressed;
public ListItemBackgroundView(Context context) {
super(context);
setWillNotDraw(false);
}
public ListItemBackgroundView(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
}
public ListItemBackgroundView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setWillNotDraw(false);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
final int w = canvas.getWidth();
final int h = canvas.getHeight();
if (mBackgroundColor == -1) {
mBackgroundColor = getResources().getColor(R.color.color_1);
mPressedBackgroundColor = getResources().getColor(R.color.color_2);
mAngleOffset = getResources().getDimensionPixelSize(R.dimen.list_view_angle_offset);
}
PATH.moveTo(0, 0);
PATH.lineTo(mAngleOffset, h * (0.35f));
PATH.lineTo(0, h);
PATH.lineTo(w, h);
PATH.lineTo(w, 0);
PATH.lineTo(0, 0);
PATH.close();
BRUSH.setStyle(Paint.Style.FILL);
BRUSH.setColor(isPressed ? mPressedBackgroundColor : mBackgroundColor);
canvas.drawPath(PATH, BRUSH);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean result = super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isPressed = true;
result = false;
invalidate();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
isPressed = false;
result = true;
invalidate();
break;
}
return result;
}
}
最佳答案
解决方案是使用StateListDrawable
作为背景。
public class ListItemStateListDrawable extends StateListDrawable {
private final int mBackgroundColor, mPressedBackgroundColor, mAngleOffset;
private final Path PATH = new Path();
private final Paint BRUSH_PRESSED = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint BRUSH = new Paint(Paint.ANTI_ALIAS_FLAG);
private boolean isDrawn = false;
private boolean isPressed = false;
public ListItemStateListDrawable(int backgroundColor, int pressedBackgroundColor, int angleOffset) {
this.mBackgroundColor = backgroundColor;
this.mPressedBackgroundColor = pressedBackgroundColor;
this.mAngleOffset = angleOffset;
}
@Override
protected boolean onStateChange(int[] stateSet) {
for(int st : stateSet){
boolean pressed = st == android.R.attr.state_pressed;
boolean not_pressed = st == android.R.attr.stateNotNeeded || st == -android.R.attr.state_pressed ||
st == android.R.attr.state_accelerated || st == android.R.attr.state_focused;
if(pressed || not_pressed){
isPressed = pressed;
invalidateSelf();
break;
}
}
return super.onStateChange(stateSet);
}
@Override
public void draw(Canvas canvas) {
if(!isDrawn){
final int w = canvas.getWidth();
final int h = canvas.getHeight();
PATH.moveTo(0, 0);
PATH.lineTo(mAngleOffset, h * (0.35f));
PATH.lineTo(0, h);
PATH.lineTo(w, h);
PATH.lineTo(w, 0);
PATH.lineTo(0, 0);
PATH.close();
BRUSH.setStyle(Paint.Style.FILL);
BRUSH.setColor(mBackgroundColor);
BRUSH_PRESSED.setStyle(Paint.Style.FILL);
BRUSH_PRESSED.setColor(mPressedBackgroundColor);
canvas.drawPath(PATH, BRUSH);
isDrawn = true;
}else {
canvas.drawPath(PATH, isPressed ? BRUSH_PRESSED : BRUSH);
}
}
}
关于android - 处理自定义 View 的不同触摸状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22557691/