关于Android自定义View使用画布的问题
Android自定义View,重写protected void onDraw(Canvas canvas)函数,但是却一直未有调用,百度一番后说是需要调用setWillNotDraw(false);我不仅在自定义View的构造函数里面调用这个函数,还尝试将它的父Layout重写在其中调用这个函数,却仍然未调用onDraw函数。
到底是什么原因呢?我发现在普通的layout里面直接调用自定义View是完全可以进入onDraw函数的,但是一旦被加入ListView中的item里,就完全没有作用了,经过大半天的努力总算找到了解决方法。
解决的方法就是重写protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)函数。因为高度为0,自然什么也看不到。
下面就看看我的自定义View的代码吧。
代码块
public class FollowDrawView extends View {
public static class FollowParams {
public boolean isFinished;//是否结束
public boolean isCurrent;//是否当前
public boolean isOnlyOne;//是否只有一个
public boolean isFirst;//是否是第一个
public float width = -1;
public float height = -1;
}
private boolean mIsFinished = false;
private boolean mIsCurrent = false;
private boolean mIsOnlyOne = false;
private boolean mIsFirst = false;
private Context mContext;
private float mWidth = -1;
private float mHeight = -1;
public FollowDrawView(Context context) {
super(context);
setWillNotDraw(false);
// initView(context, isFinished, isCurrent);
}
public FollowDrawView(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
// initView(context, isFinished, isCurrent);
}
public FollowDrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// initView(context, isFinished, isCurrent);
}
public void updateView(Context context, FollowParams params){
if (params == null) {
return;
}
mIsFinished = params.isFinished;
mIsCurrent = params.isCurrent;
mIsOnlyOne = params.isOnlyOne;
mIsFirst = params.isFirst;
mWidth = params.width;
mHeight = params.height;
mContext = context;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 创建画笔
Paint p = new Paint();
p.setColor(Color.rgb(0xeb, 0xec, 0xf1));
if (mHeight < 0 || mWidth < 0) {
return;
}
Log.i("Ondraw", "mWidth = " + mWidth + " mHeight = " + mHeight);
float lineLeft = 0;
float lineTop = 0;
float lineRight = 0;
float lineBottom = 0;
Bitmap bitmap;
Bitmap maxBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.end_location_pic);
//画圆圈图片
if (mIsCurrent) {
if (mIsFinished) {
//绘制红色圆圈
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.end_location_pic);
}
else {
//绘制绿色圆圈
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.current_location_pic);
}
}
else {
//绘制灰色圆圈
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.normal_location_pic);
}
float width = maxBitmap.getWidth();
float rectWidth = 8;
//画竖线
if (mIsCurrent) {
//竖线不画满
lineLeft = mWidth - width;
lineRight = lineLeft + rectWidth;
lineTop = getPaddingTop();
if (mIsFirst) {
lineBottom = lineTop;
}
else {
lineBottom = mHeight;
}
}
else {
//竖线画满
lineLeft = mWidth - width;
lineRight = lineLeft + rectWidth;
lineTop = 0;
if (mIsFirst) {
lineBottom = getPaddingTop() + bitmap.getHeight() / 2;
}
else {
lineBottom = mHeight;
}
}
if (!mIsOnlyOne) {
canvas.drawRect(lineLeft, lineTop, lineRight, lineBottom, p);
}
float left = 0;
float top = 0;
left = (float) (lineLeft + rectWidth / 2 - bitmap.getWidth() / 2);
top = getPaddingTop();
if (!mIsCurrent) {
top += bitmap.getHeight() / 2;
}
canvas.drawBitmap(bitmap, left, top, p);
if (mIsCurrent) {
//写:当前
p.setTextSize(CommonFun.dip2px(mContext, 15));
p.setColor(Color.rgb(0xff, 0x73, 0x73));
String curText = "当前";
if (mIsFinished) {
curText = "完成";
}
float offX = -20;
float offY = 20;
float x = lineLeft - maxBitmap.getWidth();
float y = getPaddingTop();
for (int i = 0; i < curText.length(); i++) {
String txt = curText.substring(i, i + 1);
Path path = new Path();
path.moveTo(x, y);
path.lineTo(x + 30, y);
y += 48;
canvas.drawTextOnPath(txt, path, offX, offY, p);
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mHeight < 0 || mWidth < 0) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
int measuredHeight = measureHeight(heightMeasureSpec);
int measuredWidth = measureWidth(widthMeasureSpec);
setMeasuredDimension(measuredWidth, measuredHeight);
}
private int measureHeight(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
// Default size if no limits are specified.
int result = (int) mHeight;
if (specMode == MeasureSpec.AT_MOST){//相当于我们设置为wrap_content
// Calculate the ideal size of your
// control within this maximum size.
// If your control fills the available
// space return the outer bound.
result = specSize;
mHeight = specSize;
Log.i("measureHeight", "AT_MOST height = " + mHeight);
}
else if (specMode == MeasureSpec.EXACTLY){//相当于我们设置为match_parent或者为一个具体的值
// If your control can fit within these bounds return that value.
result = specSize;
mHeight = result;
Log.i("measureHeight", "EXACTLY height = " + mHeight);
}
else {
Log.i("measureHeight", "Other height = " + mHeight);
}
return result;
}
private int measureWidth(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
// Default size if no limits are specified.
int result = (int) mWidth;
if (specMode == MeasureSpec.AT_MOST){
// Calculate the ideal size of your control
// within this maximum size.
// If your control fills the available space
// return the outer bound.
result = specSize;
mWidth = result;
Log.i("measureWidth", "AT_MOST width = " + mWidth);
}
else if (specMode == MeasureSpec.EXACTLY){
// If your control can fit within these bounds return that value.
result = specSize;
mWidth = result;
Log.i("measureWidth", "EXACTLY width = " + mWidth);
}
else {
Log.i("measureWidth", "Other width = " + mWidth);
}
return result;
}
}
xml文件:
代码块
...
<com.rsp.programmerproject.ui.FollowDrawView
android:id="@+id/fd_image_flag"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:padding="@dimen/side_padding"/>
调用文件:
代码块
@Override
public View getView(int position, View convertView, ViewGroup parent) {
...
FollowDrawView followDrawView = holder.followDrawView;
TextView infoTextView = holder.infoTextView;
TextView dateTimeTextView = holder.dateTimeTextView;
FollowDrawView.FollowParams params = new FollowDrawView.FollowParams();
params.isFinished = mBillFollowInfo.getBillFollowInfos().get(position - 1).isFinished();
params.isCurrent = position == 1 ? true : false;
params.isOnlyOne = mBillFollowInfo.getBillFollowInfos().size() < 2 ? true : false;
params.isFirst = position == mBillFollowInfo.getBillFollowInfos().size() ? true : false;
if (followDrawView != null) {
params.width = followDrawView.getMeasuredWidth();
params.height = view.getMeasuredHeight();
followDrawView.updateView(view.getContext(), params);
}
}
public class ViewHolder {
public FollowDrawView followDrawView;
public TextView infoTextView;
public TextView dateTimeTextView;
}