我知道这个问题是重复但我找不到合适的答案我的代码请看下面我有自定义视图(图表)
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import java.util.ArrayList;
public class BarView extends View {
private final int TEXT_COLOR = Color.parseColor("#9B9A9B");
private final int LINE_COLOR = Color.parseColor("#9B9A9B");
private final int BAR_RIGHT_COLOR = Color.parseColor("#e45d97");
private final int BAR_LEFT_COLOR = Color.parseColor("#C0C0C0");
private ArrayList<Integer> dataList;
private Paint textPaint;
private Paint rightBarPaint;
private Paint leftBarPaint;
private Paint linePaint;
private Rect rect;
private ArrayList<String> leftTextList = new ArrayList<String>();
// Bar
private int barWidth;
private ArrayList<Integer> barTop = new ArrayList<>();
private ArrayList<Integer> barBottom = new ArrayList<>();
private ArrayList<Integer> barPercentage = new ArrayList<>();
//Bar box calculation
private int totalViewHeight;
private int totalViewWidth;
private int leftViewPadding;
private int topViewPadding;
private int rightViewPadding;
private int bottomViewPadding;
private int totalBarRatio = 60;
private int totalBottomCount = 6;
private int centerX;
private int leftX;
public BarView(Context context) {
this(context, null);
}
//Initialize components
public BarView(Context context, AttributeSet attrs) {
super(context, attrs);
rightBarPaint = new Paint();
rightBarPaint.setAntiAlias(true);
rightBarPaint.setColor(BAR_RIGHT_COLOR);
leftBarPaint = new Paint(rightBarPaint);
leftBarPaint.setColor(BAR_LEFT_COLOR);
rect = new Rect();
leftViewPadding = GraphUtils.dip2px(context, 5);
int textSize = GraphUtils.sp2px(context, 12);
barWidth = GraphUtils.dip2px(context, 22);
topViewPadding = GraphUtils.dip2px(context, 50);
bottomViewPadding = GraphUtils.dip2px(context, 50);
rightViewPadding = GraphUtils.dip2px(context, 15);
textPaint = new Paint();
textPaint.setAntiAlias(true);
textPaint.setColor(TEXT_COLOR);
textPaint.setTextSize(textSize);
textPaint.setTypeface(Util.setCustomFont(context));
textPaint.setTextAlign(Paint.Align.CENTER);
linePaint = new Paint();
linePaint.setAntiAlias(true);
linePaint.setColor(LINE_COLOR);
dataList = new ArrayList<Integer>();
}
/**
* dataList will be reset when called is method.
*
* @param leftStringList The String ArrayList in the left.
*/
public void setLeftTextList(ArrayList<String> leftStringList) {
// this.dataList = null;
this.leftTextList = leftStringList;
setMinimumWidth(2);
}
/**
* @param list The ArrayList of Integer with the range of [0-max].
*/
public void setDataList(ArrayList<Integer> list) {
dataList = list;
postInvalidate();
}
@Override
protected void onDraw(Canvas canvas) {
totalViewHeight = getHeight();
totalViewWidth = getWidth();
//Draw OuterBox
drawOuterBox(canvas);
int i = 0;
if (dataList != null && !dataList.isEmpty()) {
for (Integer data : dataList) {
//Draw left graph value
if (data < totalBarRatio / 2 && data >= 0) {
rect.set(barPercentage.get(data - 1), barTop.get(i), centerX, barBottom.get(i));
canvas.drawRect(rect, leftBarPaint);
}
if (data > totalBarRatio / 2 && data <= totalBarRatio) {
//Draw Right graph Value
rect.set(centerX, barTop.get(i), barPercentage.get(data - 1), barBottom.get(i));
canvas.drawRect(rect, rightBarPaint);
}
i++;
}
}
}
private void drawOuterBox(Canvas canvas) {
//Draw Horizontal lines
leftX = leftViewPadding + Math.round(getHighestLeftTextWidth()) + leftViewPadding;
int availableHeight = (totalViewHeight - (topViewPadding + bottomViewPadding));
int unitHeight = availableHeight / leftTextList.size() + 1;
if (leftTextList != null && !leftTextList.isEmpty()) {
//Draw first line with top padding
canvas.drawLine(leftX, topViewPadding, totalViewWidth - rightViewPadding, topViewPadding, linePaint);
barTop.add(topViewPadding + unitHeight / 4);
barBottom.add(topViewPadding + (unitHeight / 4) * 3);
for (int i = 1; i < leftTextList.size(); i++) {
barTop.add(topViewPadding + unitHeight * i + unitHeight / 4);
barBottom.add(topViewPadding + unitHeight * i + (unitHeight / 4) * 3);
canvas.drawLine(leftX, topViewPadding + unitHeight * i, totalViewWidth - rightViewPadding, topViewPadding + unitHeight * i, linePaint);
}
//Draw last line with top padding
canvas.drawLine(0, totalViewHeight - bottomViewPadding, totalViewWidth, totalViewHeight - bottomViewPadding, linePaint);
}
//Draw Vertical lines
//Right line
canvas.drawLine(totalViewWidth - rightViewPadding, topViewPadding, totalViewWidth - rightViewPadding, totalViewHeight - bottomViewPadding, linePaint);
//Center Line
centerX = (totalViewWidth - rightViewPadding + leftX) / 2;
canvas.drawLine(centerX, topViewPadding, centerX, totalViewHeight - bottomViewPadding, linePaint);
//Left Vertical Line
canvas.drawLine(leftX, topViewPadding, leftX, totalViewHeight - bottomViewPadding, linePaint);
// Draw left Text
if (leftTextList != null && !leftTextList.isEmpty()) {
int i = 1;
for (String s : leftTextList) {
canvas.drawText(s, leftViewPadding + (getHighestLeftTextWidth() / 2), ((topViewPadding + unitHeight * i) - unitHeight / 2) + (textPaint.getTextSize() / 2), textPaint);
i++;
}
}
// Draw bottom arrow
int boxWidth = totalViewWidth - (rightViewPadding + leftX);
int width = boxWidth / totalBottomCount;
int lineHeight = bottomViewPadding / 4;
canvas.drawLine(leftX, totalViewHeight - bottomViewPadding, leftX, (totalViewHeight - bottomViewPadding) + lineHeight, linePaint);
canvas.drawLine(centerX, totalViewHeight - bottomViewPadding, centerX, (totalViewHeight - bottomViewPadding) + lineHeight, linePaint);
canvas.drawLine(totalViewWidth - rightViewPadding, totalViewHeight - bottomViewPadding, totalViewWidth - rightViewPadding, (totalViewHeight - bottomViewPadding) + lineHeight, linePaint);
canvas.drawText("-30", leftX, totalViewHeight - (bottomViewPadding / 2) + (textPaint.getTextSize() / 2), textPaint);
canvas.drawText("0", centerX, totalViewHeight - (bottomViewPadding / 2) + (textPaint.getTextSize() / 2), textPaint);
canvas.drawText("30", totalViewWidth - rightViewPadding, totalViewHeight - (bottomViewPadding / 2) + (textPaint.getTextSize() / 2), textPaint);
for (int i = 1; i < totalBottomCount; i++) {
if (i != totalBottomCount / 2) {
canvas.drawLine(leftX + (width * i), totalViewHeight - bottomViewPadding, leftX + (width * i), (totalViewHeight - bottomViewPadding) + lineHeight, linePaint);
canvas.drawText((i * 10) - 30 + "", leftX + (width * i), totalViewHeight - (bottomViewPadding / 2) + (textPaint.getTextSize() / 2), textPaint);
}
}
int unitWidth = boxWidth / totalBarRatio;
for (int i = 1; i <= totalBarRatio; i++) {
barPercentage.add(leftX + (unitWidth * i));
}
}
private float getHighestLeftTextWidth() {
String text = "";
for (String s : leftTextList) {
if (s.length() > text.length()) {
text = s;
}
}
return textPaint.measureText(text);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int mViewWidth = measureWidth(widthMeasureSpec);
int mViewHeight = measureHeight(heightMeasureSpec);
setMeasuredDimension(mViewWidth, mViewHeight);
}
private int measureWidth(int measureSpec) {
int preferred = 0;
if (leftTextList != null) {
preferred = leftTextList.size() * (barWidth);
}
return getMeasurement(measureSpec, preferred);
}
private int measureHeight(int measureSpec) {
int preferred = 222;
return getMeasurement(measureSpec, preferred);
}
private int getMeasurement(int measureSpec, int preferred) {
int specSize = MeasureSpec.getSize(measureSpec);
int measurement;
switch (MeasureSpec.getMode(measureSpec)) {
case MeasureSpec.EXACTLY:
measurement = specSize;
break;
case MeasureSpec.AT_MOST:
measurement = Math.min(preferred, specSize);
break;
default:
measurement = preferred;
break;
}
return measurement;
}
}
我用过
public void setDataList(ArrayList<Integer> list) {
dataList = list;
postInvalidate();
}
使用我的Activity中的新数据更新视图,但postInvalidate不会调用onDraw。
答案 0 :(得分:1)
根据android docs postInvalidate()方法只有在此视图附加到窗口时才能从UI线程外部调用。因此,您必须从UI线程以外的地方调用setDataList()
,或使用invalidate()
方法从UI线程更新View
,如下所示。
public void setDataList(ArrayList<Integer> list) {
dataList = list;
invalidate();
}