【发布时间】:2017-05-16 13:11:01
【问题描述】:
我正在尝试在画布上绘制 ProgressBar。我怀疑它不会自己绘制,因为 onAttachedToWindow 没有被调用......?如果我尝试绘制 TextView,它会正常显示和绘制。我需要在画布上绘制 ProgressBar,因为在 RecyclerView 加载时没有其他方法可以将其显示为装饰器https://yoda.entelect.co.za/view/9627/how-to-android-recyclerview-item-decorations
此活动只是演示如何绘制 ProgressBar。
public class DrawingActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Rect rect = new Rect();
rect.set(0, 0, 500, 500);
Bitmap bitmap = Bitmap.createBitmap(700, 700, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
//Make a new view and lay it out at the desired Rect dimensions
// TextView view = new TextView(this);
// view.setText("This is a custom drawn textview");
ProgressBar view = new ProgressBar(this, null, android.R.attr.progressBarStyle);
//Measure the view at the exact dimensions (otherwise the text won't center correctly)
int widthSpec = MeasureSpec.makeMeasureSpec(rect.width(), MeasureSpec.EXACTLY);
int heightSpec = MeasureSpec.makeMeasureSpec(rect.height(), MeasureSpec.EXACTLY);
view.measure(widthSpec, heightSpec);
//Lay the view out at the rect width and height
view.layout(0, 0, rect.width(), rect.height());
//Translate the Canvas into position and draw it
canvas.save();
canvas.translate(rect.left, rect.top);
view.draw(canvas);
canvas.restore();
//To make sure it works, set the bitmap to an ImageView
ImageView imageView = new ImageView(this);
imageView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
imageView.setScaleType(ScaleType.CENTER);
imageView.setImageBitmap(bitmap);
setContentView(imageView);
// force the invalidation of the view
ViewCompat.postInvalidateOnAnimation(view);
}
}
编辑:
为 RecyclerView 添加 Layout 装饰器:
public class LayoutItemDecorationTest extends RecyclerView.ItemDecoration {
private View view;
@LayoutRes
private int layoutRes;
private ItemPosition itemPosition;
public LayoutItemDecorationTest(@LayoutRes int layoutRes, ItemPosition position) {
this.layoutRes = layoutRes;
this.itemPosition = position;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
// view needs to be instantiated here, otherwise view animation doesn't work properly
this.view = View.inflate(parent.getContext(), layoutRes, null);
// adapter items count
int count = parent.getAdapter().getItemCount();
final int position = parent.getChildAdapterPosition(view);
int height = view.getMeasuredHeight();
if (itemPosition == ItemPosition.ALL) {
outRect.set(0, 0, 0, height);
} else if (itemPosition == ItemPosition.FIRST) {
if (position == 0) {
outRect.set(0, 0, 0, height);
}
} else if (itemPosition == ItemPosition.LAST) {
if (position == count - 1) {
outRect.set(0, 0, 0, height);
}
}
}
/**
* Using onDrawOver to overlay any other existing decorators below
*/
@Override
public void onDrawOver(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
canvas.save();
// adapter items count
int count = parent.getAdapter().getItemCount();
// iterate through visible children
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(child);
if (itemPosition == ItemPosition.ALL) {
drawView(canvas, this.view, parent, child);
} else if (itemPosition == ItemPosition.FIRST) {
if (position == 0) {
drawView(canvas, this.view, parent, child);
}
} else if (itemPosition == ItemPosition.LAST) {
if (position == count - 1) {
drawView(canvas, this.view, parent, child);
}
}
}
canvas.restore();
// animation stops if we don't invalidate on the next animation time step
ViewCompat.postInvalidateOnAnimation(parent);
}
private void drawView(Canvas canvas, View view, View parent, View child) {
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
// canvas translation coordinates
int left = parent.getPaddingLeft();
int top = child.getBottom() + params.bottomMargin;
// canvas must be translated to the correct location, otherwise view will be drawn on 0,0
canvas.translate(left, top);
// view must be measure and layout
view.measure(MeasureSpec.getSize(child.getMeasuredWidth()), MeasureSpec.getSize(child.getMeasuredHeight()));
view.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
// draw the view on canvas
view.draw(canvas);
}
}
【问题讨论】:
-
只需将
ProgressBar添加到您的RecyclerViews 项目视图中 -
我想避免这样做,因为我想要一个干净的项目布局。这也意味着我应该对每个项目的状态负责,这就是我试图摆脱的。
-
所以创建一个自定义
RecyclerView.Adapter,添加ProgressBar并将其用作适配器的基类 - 所以您需要做的就是将... extends RecyclerView.Adapter<...更改为... extends MyAdapter<... -
如果你想使用装饰器然后在
Canvas级别上使用它,直接进行绘制(而不使用任何分离的ProgressBar),只需像这样绘制Drawables:pastebin.com/QV9MsPjg -
试一试,当然需要根据自己的需要进行调整
标签: android canvas progress-bar draw android-progressbar