自定义视图无效

时间:2015-07-03 06:17:35

标签: java android

我知道这个问题是重复但我找不到合适的答案我的代码请看下面我有自定义视图(图表)

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。

1 个答案:

答案 0 :(得分:1)

根据android docs postInvalidate()方法只有在此视图附加到窗口时才能从UI线程外部调用。因此,您必须从UI线程以外的地方调用setDataList(),或使用invalidate()方法从UI线程更新View,如下所示。

public void setDataList(ArrayList<Integer> list) {
    dataList = list;
    invalidate();
}