Android invalidateDrawable() 不工作
Android invalidateDrawable() not working
我在自定义视图中有一堆可绘制对象。我希望用户能够按下一个或多个可绘制对象并改变颜色。目前,每个可绘制对象只是一个具有两种状态的 StateListDrawable
:state_pressed
和未按下。每次我按下可绘制对象时,setState
returns true 所以我假设它实际上已更改,但我没有看到可绘制图像发生变化。 invalidateDrawable
什么都没做吗?我究竟做错了什么?如何在按下时重绘一个可绘制对象而不需要调用 customView.invalidate()
并每次都重绘整个对象?我最初是这样做的,但发现我的应用 运行 非常 slowly/inefficiently。谢谢!
流量:
Custom View (contains set of our custom class - TouchKey)
- Custom class TouchKey containing drawable and info
- Upon press or release, custom class finds which drawable to change
这是 TouchKey
class 中的按钮触摸代码(MyTouch 是自定义 class 跟踪 android 设备上的所有触摸):
public void pressed(MyTouch touch) {
boolean successfulStateChange = this.drawable.setState(new int[]{android.
R.attr.state_pressed});
this.customView.invalidateDrawable(drawable);
}
public void released(MyTouch touch) {
boolean successfulStateChange = this.drawable.setState(new int[]{-android.
R.attr.state_pressed});
this.customView.invalidateDrawable(drawable);
}
如何在我的自定义视图中绘制我的 StateListDrawable
:
public class CustomView extends View {
private TreeMap<Integer, TouchKey> keymap;
/* Initialization Code Stuff Here - call drawKey */
// StateListDrawable Creation
private StateListDrawable drawKey(Canvas canvas, int bounds_l,
int bounds_t, int bounds_r, int bounds_b)
throws Resources.NotFoundException, XmlPullParserException, IOException {
StateListDrawable key = new StateListDrawable();
key.addState(new int[]{android.R.attr.state_pressed},
ContextCompat.getDrawable(mContext, R.drawable.key_pressed));
key.addState(new int[]{-android.R.attr.state_pressed},
ContextCompat.getDrawable(mContext, R.drawable.key_released));
key.setBounds(bound_l, bounds_t, bounds_r, bounds_b);
key.draw(canvas);
return key;
}
}
I was doing that originally but found that my app ran very slowly/inefficiently
如果这样做,那么您在代码中的某些地方会有很大的优势,或者(我想)在绘制之前不缩放图像。因此,请尝试在您的代码中找到对系统具有巨大优势的逻辑。因为View.invalidate()
这么快的方法。
其他 0,02$ :
我想你会开发类似键盘的东西。对于这种情况,您需要使 canvas 的区域无效。
View.invalidate(new Rect(0, 0, 49, 49));
我也遇到了这个问题,不过最后还是解决了。这个问题的原因是你在上下文中使用的 Drawable
对象没有通过调用 setBounds(Rect)
设置它是 Bounds
,所以它的 Bounds
是 Rect(0,0,0,0)
默认情况下。这导致 Drawable
附加的 View
的 invalidateDrawable()
不工作。
查看 View.invalidateDrawable()
:
@Override
public void invalidateDrawable(@NonNull Drawable drawable) {
if (verifyDrawable(drawable)) {
final Rect dirty = drawable.getDirtyBounds();
final int scrollX = mScrollX;
final int scrollY = mScrollY;
invalidate(dirty.left + scrollX, dirty.top + scrollY,
dirty.right + scrollX, dirty.bottom + scrollY);
rebuildOutline();
}
}
查看Drawable.getDirtyBounds():
/**
* Return the drawable's dirty bounds Rect. Note: for efficiency, the
* returned object may be the same object stored in the drawable (though
* this is not guaranteed).
* <p>
* By default, this returns the full drawable bounds. Custom drawables may
* override this method to perform more precise invalidation.
*
* @return The dirty bounds of this drawable
*/
@NonNull
public Rect getDirtyBounds() {
return getBounds();
}
所以 Rect dirty 是 Rect(0,0,0,0)
,如果你没有设置 Drawable.Bounds
。因此 View.invalidate()
不起作用。
所以你要做的就是在代码的某个地方设置Drawable.Bounds
,比如:
@Override
public void draw(@NonNull Canvas canvas) {
Rect localRect = canvas.getClipBounds();
this.setBounds(localRect);
...
}
我在自定义视图中有一堆可绘制对象。我希望用户能够按下一个或多个可绘制对象并改变颜色。目前,每个可绘制对象只是一个具有两种状态的 StateListDrawable
:state_pressed
和未按下。每次我按下可绘制对象时,setState
returns true 所以我假设它实际上已更改,但我没有看到可绘制图像发生变化。 invalidateDrawable
什么都没做吗?我究竟做错了什么?如何在按下时重绘一个可绘制对象而不需要调用 customView.invalidate()
并每次都重绘整个对象?我最初是这样做的,但发现我的应用 运行 非常 slowly/inefficiently。谢谢!
流量:
Custom View (contains set of our custom class - TouchKey)
- Custom class TouchKey containing drawable and info
- Upon press or release, custom class finds which drawable to change
这是 TouchKey
class 中的按钮触摸代码(MyTouch 是自定义 class 跟踪 android 设备上的所有触摸):
public void pressed(MyTouch touch) {
boolean successfulStateChange = this.drawable.setState(new int[]{android.
R.attr.state_pressed});
this.customView.invalidateDrawable(drawable);
}
public void released(MyTouch touch) {
boolean successfulStateChange = this.drawable.setState(new int[]{-android.
R.attr.state_pressed});
this.customView.invalidateDrawable(drawable);
}
如何在我的自定义视图中绘制我的 StateListDrawable
:
public class CustomView extends View {
private TreeMap<Integer, TouchKey> keymap;
/* Initialization Code Stuff Here - call drawKey */
// StateListDrawable Creation
private StateListDrawable drawKey(Canvas canvas, int bounds_l,
int bounds_t, int bounds_r, int bounds_b)
throws Resources.NotFoundException, XmlPullParserException, IOException {
StateListDrawable key = new StateListDrawable();
key.addState(new int[]{android.R.attr.state_pressed},
ContextCompat.getDrawable(mContext, R.drawable.key_pressed));
key.addState(new int[]{-android.R.attr.state_pressed},
ContextCompat.getDrawable(mContext, R.drawable.key_released));
key.setBounds(bound_l, bounds_t, bounds_r, bounds_b);
key.draw(canvas);
return key;
}
}
I was doing that originally but found that my app ran very slowly/inefficiently
如果这样做,那么您在代码中的某些地方会有很大的优势,或者(我想)在绘制之前不缩放图像。因此,请尝试在您的代码中找到对系统具有巨大优势的逻辑。因为View.invalidate()
这么快的方法。
其他 0,02$ :
我想你会开发类似键盘的东西。对于这种情况,您需要使 canvas 的区域无效。
View.invalidate(new Rect(0, 0, 49, 49));
我也遇到了这个问题,不过最后还是解决了。这个问题的原因是你在上下文中使用的 Drawable
对象没有通过调用 setBounds(Rect)
设置它是 Bounds
,所以它的 Bounds
是 Rect(0,0,0,0)
默认情况下。这导致 Drawable
附加的 View
的 invalidateDrawable()
不工作。
查看 View.invalidateDrawable()
:
@Override
public void invalidateDrawable(@NonNull Drawable drawable) {
if (verifyDrawable(drawable)) {
final Rect dirty = drawable.getDirtyBounds();
final int scrollX = mScrollX;
final int scrollY = mScrollY;
invalidate(dirty.left + scrollX, dirty.top + scrollY,
dirty.right + scrollX, dirty.bottom + scrollY);
rebuildOutline();
}
}
查看Drawable.getDirtyBounds():
/**
* Return the drawable's dirty bounds Rect. Note: for efficiency, the
* returned object may be the same object stored in the drawable (though
* this is not guaranteed).
* <p>
* By default, this returns the full drawable bounds. Custom drawables may
* override this method to perform more precise invalidation.
*
* @return The dirty bounds of this drawable
*/
@NonNull
public Rect getDirtyBounds() {
return getBounds();
}
所以 Rect dirty 是 Rect(0,0,0,0)
,如果你没有设置 Drawable.Bounds
。因此 View.invalidate()
不起作用。
所以你要做的就是在代码的某个地方设置Drawable.Bounds
,比如:
@Override
public void draw(@NonNull Canvas canvas) {
Rect localRect = canvas.getClipBounds();
this.setBounds(localRect);
...
}