天天看點

自定義時間軸控件

首先我們來看看效果圖

自定義時間軸控件

接下來具體代碼實作,本人不善講解,故所有邏輯都在代碼中 請關注代碼吧。

/**
 * 簡易帶有時間軸的linearlayout
 */
public class UnderLineLinearLayout extends LinearLayout {
    //=============================================================line gravity常量定義
    public static final int GRAVITY_LEFT = 2;
    public static final int GRAVITY_RIGHT = 4;
    public static final int GRAVITY_MIDDLE = 0;
    public static final int GRAVITY_TOP = 1;
    public static final int GRAVITY_BOTTOM = 3;
    //=============================================================元素定義
    private Bitmap mIcon;
    //line location
    private int lineMarginSide;
    private int lineDynamicDimen;
    //line property
    private int lineStrokeWidth;
    private int lineColor;
    //point property
    private int pointSize;
    private int pointColor;

    //=============================================================paint
    private Paint linePaint;
    private Paint pointPaint;
    //=============================================================其他輔助參數
    //第一個點的位置
    private int firstX;
    private int firstY;
    //最後一個圖的位置
    private int lastX;
    private int lastY;
    //預設垂直
    private int curOrientation = VERTICAL;

    //line gravity(預設垂直的左邊)
    private int lineGravity = GRAVITY_LEFT;

    private Context mContext;

    //開關
    private boolean drawLine = true;

    private int rootLeft;
    private int rootMiddle;
    private int rootRight;
    private int rootTop;
    private int rootBottom;
    //參照點
    private int sideRelative;

    public UnderLineLinearLayout(Context context) {
        this(context, null);
    }

    public UnderLineLinearLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public UnderLineLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.UnderLineLinearLayout);
        lineMarginSide = attr.getDimensionPixelOffset(R.styleable.UnderLineLinearLayout_line_margin_side, 10);
        lineDynamicDimen = attr.getDimensionPixelOffset(R.styleable.UnderLineLinearLayout_line_dynamic_dimen, 0);
        lineStrokeWidth = attr.getDimensionPixelOffset(R.styleable.UnderLineLinearLayout_line_stroke_width, 2);
        lineColor = attr.getColor(R.styleable.UnderLineLinearLayout_line_color, 0xff3dd1a5);
        pointSize = attr.getDimensionPixelSize(R.styleable.UnderLineLinearLayout_point_size, 8);
        pointColor = attr.getColor(R.styleable.UnderLineLinearLayout_point_color, 0xff3dd1a5);
        lineGravity = attr.getInt(R.styleable.UnderLineLinearLayout_line_gravity, GRAVITY_LEFT);

        int iconRes = attr.getResourceId(R.styleable.UnderLineLinearLayout_icon_src, R.drawable.spot);
        BitmapDrawable temp = null;
        if (iconRes != 0) {
            temp = (BitmapDrawable) context.getResources().getDrawable(iconRes);
        }

        if (temp != null) {
            mIcon = temp.getBitmap();
        }

        curOrientation = getOrientation();
        attr.recycle();
        setWillNotDraw(false);
        initView(context);
    }

    private void initView(Context context) {
        this.mContext = context;

        linePaint = new Paint();
        linePaint.setAntiAlias(true);
        linePaint.setDither(true);
        linePaint.setColor(lineColor);
        linePaint.setStrokeWidth(lineStrokeWidth);
        linePaint.setStyle(Paint.Style.FILL_AND_STROKE);

        pointPaint = new Paint();
        pointPaint.setAntiAlias(true);
        pointPaint.setDither(true);
        pointPaint.setColor(pointColor);
        pointPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        calculateSideRelative();
        if (drawLine) {
            drawTimeLine(canvas);
        }
    }

    private void calculateSideRelative() {
        rootLeft = getLeft();
        rootTop = getTop();
        rootRight = getRight();
        rootBottom = getBottom();
        if (curOrientation == VERTICAL) rootMiddle = (rootLeft + rootRight) >> 1;
        if (curOrientation == HORIZONTAL) rootMiddle = (rootTop + rootBottom) >> 1;

        boolean isCorrect = (lineGravity == GRAVITY_MIDDLE || (lineGravity + curOrientation) % 2 != 0);
        if (isCorrect) {
            switch (lineGravity) {
                case GRAVITY_TOP:
                    sideRelative = rootTop;
                    break;
                case GRAVITY_BOTTOM:
                    sideRelative = rootBottom;
                    break;
                case GRAVITY_LEFT:
                    sideRelative = rootLeft;
                    break;
                case GRAVITY_RIGHT:
                    sideRelative = rootRight;
                    break;
                case GRAVITY_MIDDLE:
                    sideRelative = rootMiddle;
                    break;
            }
        } else {
            sideRelative = 0;
        }
    }

    private void drawTimeLine(Canvas canvas) {
        int childCount = getChildCount();

        if (childCount > 0) {
            //大于1,證明至少有2個,也就是第一個和第二個之間連成線,第一個和最後一個分别有點/icon
            if (childCount > 1) {
                switch (curOrientation) {
                    case VERTICAL:
                        drawFirstChildViewVertical(canvas);
                        drawLastChildViewVertical(canvas);
                        drawBetweenLineVertical(canvas);
                        break;
                    case HORIZONTAL:
                        drawFirstChildViewHorizontal(canvas);
                        drawLastChildViewHorizontal(canvas);
                        drawBetweenLineHorizontal(canvas);
                        break;
                    default:
                        break;
                }
            } else if (childCount == 1) {
                switch (curOrientation) {
                    case VERTICAL:
                        drawFirstChildViewVertical(canvas);
                        break;
                    case HORIZONTAL:
                        drawFirstChildViewHorizontal(canvas);
                        break;
                    default:
                        break;
                }
            }
        }
    }

    //=============================================================Vertical Draw
    private void drawFirstChildViewVertical(Canvas canvas) {
        if (getChildAt(0) != null) {
            int top = getChildAt(0).getTop();
            //記錄值
            firstX = sideRelative >= rootMiddle ? (sideRelative - lineMarginSide) : (sideRelative + lineMarginSide);
            firstY = top + getChildAt(0).getPaddingTop() + lineDynamicDimen;
            //畫一個圓
            canvas.drawCircle(firstX, firstY, pointSize, pointPaint);
        }
    }

    private void drawLastChildViewVertical(Canvas canvas) {
        if (getChildAt(getChildCount() - 1) != null) {
            int top = getChildAt(getChildCount() - 1).getTop();
            //記錄值
            lastX = (sideRelative >= rootMiddle ? (sideRelative - lineMarginSide) : (sideRelative + lineMarginSide)) - (mIcon
                    .getWidth() >> 1);
            lastY = top + getChildAt(getChildCount() - 1).getPaddingTop() + lineDynamicDimen;
            //畫一個圖
            canvas.drawBitmap(mIcon, lastX, lastY, null);
        }
    }

    private void drawBetweenLineVertical(Canvas canvas) {
        //畫剩下的
        canvas.drawLine(firstX, firstY, firstX, lastY, linePaint);
        for (int i = 0; i < getChildCount() - 1; i++) {
            //畫了線,就畫圓
            if (getChildAt(i) != null && i != 0) {
                int top = getChildAt(i).getTop();
                //記錄值
                int Y = top + getChildAt(i).getPaddingTop() + lineDynamicDimen;
                canvas.drawCircle(firstX, Y, pointSize, pointPaint);
            }
        }
    }

    //=============================================================Horizontal Draw
    private void drawFirstChildViewHorizontal(Canvas canvas) {
        if (getChildAt(0) != null) {
            int left = getChildAt(0).getLeft();
            //記錄值
            firstX = left + getChildAt(0).getPaddingLeft() + lineDynamicDimen;
            firstY = sideRelative >= rootMiddle ? (sideRelative - lineMarginSide) : (sideRelative + lineMarginSide);
            //畫一個圓
            canvas.drawCircle(firstX, firstY, pointSize, pointPaint);
        }
    }

    private void drawLastChildViewHorizontal(Canvas canvas) {
        if (getChildAt(getChildCount() - 1) != null) {
            int left = getChildAt(getChildCount() - 1).getLeft();
            //記錄值
            lastX = left + getChildAt(getChildCount() - 1).getPaddingLeft() + lineDynamicDimen;
            lastY = (sideRelative >= rootMiddle ? (sideRelative - lineMarginSide) : (sideRelative + lineMarginSide)) - (mIcon
                    .getWidth() >> 1);
            //畫一個圖
            canvas.drawBitmap(mIcon, lastX, lastY, null);
        }
    }

    private void drawBetweenLineHorizontal(Canvas canvas) {
        //畫剩下的線
        canvas.drawLine(firstX, firstY, lastX, firstY, linePaint);
        for (int i = 0; i < getChildCount() - 1; i++) {
            //畫了線,就畫圓
            if (getChildAt(i) != null && i != 0) {
                int left = getChildAt(i).getLeft();
                //記錄值
                int x = left + getChildAt(i).getPaddingLeft() + lineDynamicDimen;
                canvas.drawCircle(x, firstY, pointSize, pointPaint);
            }
        }
    }

    //=============================================================Getter/Setter

    @Override
    public void setOrientation(int orientation) {
        super.setOrientation(orientation);
        this.curOrientation = orientation;
        invalidate();
    }

    public int getLineStrokeWidth() {
        return lineStrokeWidth;
    }

    public void setLineStrokeWidth(int lineStrokeWidth) {
        this.lineStrokeWidth = lineStrokeWidth;
        invalidate();
    }

    public boolean isDrawLine() {
        return drawLine;
    }

    public void setDrawLine(boolean drawLine) {
        this.drawLine = drawLine;
        invalidate();
    }

    public Paint getLinePaint() {
        return linePaint;
    }

    public void setLinePaint(Paint linePaint) {
        this.linePaint = linePaint;
        invalidate();
    }

    public int getPointSize() {
        return pointSize;
    }

    public void setPointSize(int pointSize) {
        this.pointSize = pointSize;
        invalidate();
    }

    public int getPointColor() {
        return pointColor;
    }

    public void setPointColor(int pointColor) {
        this.pointColor = pointColor;
        invalidate();
    }

    public Paint getPointPaint() {
        return pointPaint;
    }

    public void setPointPaint(Paint pointPaint) {
        this.pointPaint = pointPaint;
        invalidate();
    }

    public int getLineColor() {
        return lineColor;
    }

    public void setLineColor(int lineColor) {
        this.lineColor = lineColor;
        invalidate();
    }

    public int getLineMarginSide() {
        return lineMarginSide;
    }

    public void setLineMarginSide(int lineMarginSide) {
        this.lineMarginSide = lineMarginSide;
        invalidate();
    }

    public int getLineDynamicDimen() {
        return lineDynamicDimen;
    }

    public void setLineDynamicDimen(int lineDynamicDimen) {
        this.lineDynamicDimen = lineDynamicDimen;
        invalidate();
    }

    public Bitmap getIcon() {
        return mIcon;
    }

    public void setIcon(Bitmap icon) {
        mIcon = icon;
    }

    public void setIcon(int resId) {
        if (resId == 0) return;
        BitmapDrawable temp = (BitmapDrawable) mContext.getResources().getDrawable(resId);
        if (temp != null) mIcon = temp.getBitmap();
        invalidate();
    }

    public int getLineGravity() {
        return lineGravity;
    }

    public void setLineGravity(int lineGravity) {
        this.lineGravity = lineGravity;
        invalidate();
    }

    public OnUnderLineLinkListener underLineLinkListener;

    public UnderLineLinearLayout build(Context context, OnUnderLineLinkListener underLineLinkListener) {
        this.underLineLinkListener = underLineLinkListener;
        LayoutInflater rootInflater = LayoutInflater.from(context);
        if (underLineLinkListener != null) {
            View rootView = rootInflater.inflate(underLineLinkListener.initWidgetsView(), this, false);
            addView(rootView);
            UnderLineItemViewHold viewHold = underLineLinkListener.initItemViewHold(rootView);
            underLineLinkListener.initWidgetsEvent(viewHold);
        }
        return this;
    }
}      

用到的時間軸接口

/**
 * 時間軸接口
 * Created by Home-Pc on 2017/7/18.
 */

public interface OnUnderLineLinkListener<T extends UnderLineItemViewHold> {

    int initWidgetsView();

    T initItemViewHold(View itemView);

    void initWidgetsEvent(T hold);
}      

時間軸ViewHold

/**
 * 時間軸VIiewHold
 * Created by Home-Pc on 2017/7/19.
 */

public abstract class UnderLineItemViewHold {

    public UnderLineItemViewHold(View itemView){

    }
}      

activity需要實作的代碼

public class MyItemViewHold extends UnderLineItemViewHold {
    TextView inResultTvShow, inResultTime;

    public MyItemViewHold(View itemView) {
        super(itemView);
        inResultTvShow = (TextView) itemView.findViewById(R.id.inResultTvShow);
        inResultTime = (TextView) itemView.findViewById(R.id.inResultTime);
    }
}

private void initView(final String contentText, final int textColor, final String timeText, final int timeColor) {

    myUnderLineaLinerLayout.build(this, new OnUnderLineLinkListener<MyItemViewHold>() {
        @Override
        public int initWidgetsView() {
            return R.layout.v_investment_result_item_layout;
        }

        @Override
        public UnderLineItemViewHold initItemViewHold(View itemView) {
            return new MyItemViewHold(itemView);
        }

        @Override
        public void initWidgetsEvent(MyItemViewHold hold) {
            hold.inResultTvShow.setText(contentText == null ? "" : contentText);
            hold.inResultTvShow.setTextColor(ContextCompat.getColor(MainActivity.this, textColor));

            hold.inResultTime.setText(timeText == null ? "" : timeText);
            hold.inResultTime.setTextColor(ContextCompat.getColor(MainActivity.this, timeColor));
        }
    });
}      

activity 調用方法

initView("投資時間", R.color.blackColor, "2017-7-18 17:24", R.color.color666666);
initView("開始計算收益", R.color.color666666, "2017-7-18 17:24", R.color.color666666);
initView("開始計算收益", R.color.color666666, "2017-7-18 17:24", R.color.color666666);
initView("開始計算收益", R.color.color666666, "2017-7-18 17:24", R.color.color666666);