我有一个自定义视图,扩展RelativeLayout
并将其用作ListView
中的列表项。它基本上是一个左边有一个时髦角度的矩形。根据我在onTouchEvent
中返回的内容,我最终可能处于两种可能的状态:
我之前从未做过这种类型的自定义视图,但我真的很感激建议。我认为我错过了一些简单的事情,但是我现在花费了太多时间来继续这样做而没有提出问题!
以下是代码:
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;
}
}
答案 0 :(得分:2)
解决方案是使用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);
}
}
}
答案 1 :(得分:2)
使用StateListDrawable并通过addState添加状态是一种很好的标准方法,但你可以通过以下方式缩短它:
class MyStateListDrawable extends StateListDrawable {
@Override
protected boolean onStateChange(int[] stateSet) {
invalidateSelf();
return super.onStateChange(stateSet);
}
@Override
public void draw(Canvas canvas) {
int[] state = getState();
Log.d(TAG, "draw " + StateSet.dump(getState()));
// remove states you dont want or add you do
if (isA(android.R.attr.state_pressed)) {
Log.d(TAG, "draw state_pressed");
canvas.drawColor(0xffff0000);
} else
if (isA(android.R.attr.state_focused)) {
Log.d(TAG, "draw state_focused");
canvas.drawColor(0xffff0000);
} else
if (isA(android.R.attr.state_selected)) {
Log.d(TAG, "draw state_selected");
canvas.drawColor(0xffffff00);
} else {
Log.d(TAG, "draw default state");
canvas.drawColor(0xff0000ff);
}
}
private boolean isA(int i) {
int[] state = getState();
for (int st : state) {
if (st == i) {
return true;
}
}
return false;
}
}