Android笔记:自定义view拆线图

先看一下效果图:
这里写图片描述
这个demo是横向可滑动的
这里写图片描述
1.先在values下建一个attrs文件:定义需要的变量:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="LineChar">
        <attr  name="xylinecolor" format="color"/><!-- xy坐标轴颜色 -->
        <attr  name="xylinewidth" format="dimension"/><!-- xy坐标轴宽度 -->
        <attr  name="xytextcolor" format="color"/><!-- xy坐标轴文字颜色 -->
        <attr name="xytextsize" format="dimension"/><!-- xy坐标轴文字大小 -->
        <attr name="linecolor" format="color"/><!-- 折线图中折线的颜色 -->
        <attr name="interval" format="dimension"/><!-- x轴各个坐标点水平间距 -->
        <attr name="bgcolor" format="color"/><!-- 背景颜色 -->
    </declare-styleable>
</resources>

2.接下来自定义view LineCharView

package com.dfwy.cxy.lineview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by cxy on 2017/2/6.
 */

public class LineCharView extends View {
    private int xori;//圆点x坐标
    private int yori;//圆点y坐标
    private int xinit;//第一个点x坐标
    private int minXinit;//在移动时,第一个点允许最小的x坐标
    private int maxXinit;//在移动时,第一个点允许允许最大的x坐标
    private int xylinecolor;//xy坐标轴颜色
    private int xylinewidth;//xy坐标轴大小
    private int xytextcolor;//xy坐标轴文字颜色
    private int xytextsize;//xy坐标轴文字大小
    private int linecolor;//折线的颜色
    private int interval;//坐标间的间隔
    private int bgColor;//背景颜色
    private List<String> x_coords;//x坐标点的值
    private List<String> x_coord_values;//每个点状态值


    private int width;//控件宽度
    private int heigth;//控件高度
    private int imageWidth;//表情的宽度
    private float textwidth;//y轴文字的宽度
    float startX=0;//滑动时候,上一次手指的x坐标
    public LineCharView(Context context) {
        super(context);
    }

    public LineCharView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray typedArray= context.obtainStyledAttributes(attrs, R.styleable.LineChar);
        xylinecolor=typedArray.getColor(R.styleable.LineChar_xylinecolor, Color.GRAY);
        xylinewidth=typedArray.getInt(R.styleable.LineChar_xylinewidth, 5);
        xytextcolor=typedArray.getColor(R.styleable.LineChar_xytextcolor, Color.BLACK);
        xytextsize=typedArray.getLayoutDimension(R.styleable.LineChar_xytextsize, 20);
        linecolor=typedArray.getColor(R.styleable.LineChar_linecolor, Color.GRAY);
        interval=typedArray.getLayoutDimension(R.styleable.LineChar_interval, 100);
        bgColor=typedArray.getColor(R.styleable.LineChar_bgcolor, Color.WHITE);
        typedArray.recycle();
        x_coords=new ArrayList<String>();
        x_coord_values=new ArrayList<String>();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        if (changed){
            width  = getWidth();
            heigth = getHeight();
            Paint paint = new Paint();
            paint.setTextSize(xytextsize);
            xori=(int) (textwidth+6+2*xylinewidth);//6 为与y轴的间隔
            yori=heigth-xytextsize-2*xylinewidth-3;//3为与x轴的间隔
            xinit = interval/2+xori;
            imageWidth = BitmapFactory.decodeResource(getResources(),R.mipmap.facea).getWidth();
            minXinit = width-xori-x_coords.size()*interval;
            maxXinit = xinit;
            setBackgroundColor(bgColor);
        }
        super.onLayout(changed, left, top, right, bottom);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawX(canvas);
        drawY(canvas);
        drawXY(canvas);
    }
    //画Y轴坐标点
    private void drawY(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(xylinecolor);
        paint.setStyle(Paint.Style.FILL);
        for (int i = 1;i<5;i++){
            canvas.drawCircle(xori,yori-(i * interval/2),xylinewidth*2,paint);
        }
        paint.setTextSize(xytextsize);
        paint.setColor(xytextcolor);
        canvas.drawText("D",xori-textwidth+16-xylinewidth,yori-(2*interval)+xytextsize/2,paint);
        canvas.drawText("C",xori-textwidth+16-xylinewidth,(float)(yori-(1.5*interval)+xytextsize/2),paint);
        canvas.drawText("B",xori-textwidth+16-xylinewidth,yori-interval+xytextsize/2,paint);
        canvas.drawText("A",xori-textwidth+16-xylinewidth,(float)(yori-(0.5*interval)+xytextsize/2),paint);

    }
    //画X轴坐标点,折线,表情
    private void drawX(Canvas canvas) {
        Paint x_coordPaint = new Paint();
        Log.i("xinit",xinit+"");
        x_coordPaint.setTextSize(xytextsize);
        x_coordPaint.setStyle(Paint.Style.FILL);
        Path path = new Path();
        //画坐标点
        for (int i = 0;i<x_coords.size();i++){
            int x = i*interval+xinit;
            if(i==0){
                path.moveTo(x, getYValue(x_coord_values.get(i)));
            }else{
                path.lineTo(x, getYValue(x_coord_values.get(i)));
            }
            x_coordPaint.setColor(xylinecolor);
            canvas.drawCircle(x, yori-50, xylinewidth*2, x_coordPaint);
            String text=x_coords.get(i);
            x_coordPaint.setColor(xytextcolor);
            canvas.drawText(text, x-x_coordPaint.measureText(text)/2, yori+xytextsize+xylinewidth*2-50, x_coordPaint);
        }

        x_coordPaint.setStyle(Paint.Style.STROKE);
        x_coordPaint.setStrokeWidth(xylinewidth);
        x_coordPaint.setColor(linecolor);
        //画折线
        canvas.drawPath(path, x_coordPaint);


        //画表情
        for(int i=0;i<x_coords.size();i++){
            int x=i*interval+xinit;
            canvas.drawBitmap(getYBitmap(x_coord_values.get(i)), x-imageWidth/2, getYValue(x_coord_values.get(i))-imageWidth/2, x_coordPaint);
        }


        //将折线超出x轴坐标的部分截取掉
        x_coordPaint.setStyle(Paint.Style.FILL);
        x_coordPaint.setColor(bgColor);
        x_coordPaint.setXfermode(new PorterDuffXfermode( PorterDuff.Mode.SRC_OVER));
        RectF rectF=new RectF(0, 0, xori, heigth);
        canvas.drawRect(rectF, x_coordPaint);
    }
    //画坐标轴
    private void drawXY(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(xylinecolor);
        paint.setStrokeWidth(xylinewidth);
        Log.i("tag","==="+xori+"====0"+"===="+xori+"===="+yori);
        Log.i("tag","==="+xori+"===="+yori+"===="+width+"===="+yori);
        //画Y轴
        canvas.drawLine(xori,yori-(2*interval)+xytextsize/2-200,xori,yori-50,paint);
        //画X轴
        canvas.drawLine(xori,yori-50,width,yori-50,paint);
    }
    //得到y坐标
    private float getYValue(String value){
        if (value.equalsIgnoreCase("A")){
            return yori-interval/2;
        }
        else if(value.equalsIgnoreCase("B")){
            return yori-interval;
        }
        else if(value.equalsIgnoreCase("C")){
            return (float) (yori-interval*1.5);
        }
        else if(value.equalsIgnoreCase("D")){
            return yori-interval*2;
        }else{
            return yori;
        }
    }
    //得到表情图
    private Bitmap getYBitmap(String value){
        Bitmap bitmap = null;
        if (value.equalsIgnoreCase("A")){
            bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.facea);
        }
        else if (value.equalsIgnoreCase("B")){
            bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.faceb);
        }
        else if (value.equalsIgnoreCase("C")){
            bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.facec);
        }
        else if (value.equalsIgnoreCase("D")){
            bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.faced);
        }
        return bitmap;
    }

    public boolean onTouchEvent(MotionEvent event){
        //如果不用滑动就可以展示所有数据,就不让滑动
        if (interval*x_coord_values.size()<=width-xori){
            return false;
        }
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                startX=event.getX();
                break;
            case MotionEvent.ACTION_MOVE:
                float dis = event.getX()-startX;
                startX = event.getX();
                if (xinit+dis>maxXinit){
                    xinit=maxXinit;
                }else if(xinit+dis<minXinit){
                    xinit= minXinit;
                }else{
                    xinit= (int) (xinit+dis);
                }
                invalidate();
                break;
        }
        return true;
    }

    public int getXori() {
        return xori;
    }

    public void setXori(int xori) {
        this.xori = xori;
    }

    public int getYori() {
        return yori;
    }

    public void setYori(int yori) {
        this.yori = yori;
    }

    public int getXinit() {
        return xinit;
    }

    public void setXinit(int xinit) {
        this.xinit = xinit;
    }

    public int getMinXinit() {
        return minXinit;
    }

    public void setMinXinit(int minXinit) {
        this.minXinit = minXinit;
    }

    public int getMaxXinit() {
        return maxXinit;
    }

    public void setMaxXinit(int maxXinit) {
        this.maxXinit = maxXinit;
    }

    public int getXylinecolor() {
        return xylinecolor;
    }

    public void setXylinecolor(int xylinecolor) {
        this.xylinecolor = xylinecolor;
    }

    public int getXylinewidth() {
        return xylinewidth;
    }

    public void setXylinewidth(int xylinewidth) {
        this.xylinewidth = xylinewidth;
    }

    public int getXytextcolor() {
        return xytextcolor;
    }

    public void setXytextcolor(int xytextcolor) {
        this.xytextcolor = xytextcolor;
    }

    public int getXytextsize() {
        return xytextsize;
    }

    public void setXytextsize(int xytextsize) {
        this.xytextsize = xytextsize;
    }

    public int getLinecolor() {
        return linecolor;
    }

    public void setLinecolor(int linecolor) {
        this.linecolor = linecolor;
    }

    public int getInterval() {
        return interval;
    }

    public void setInterval(int interval) {
        this.interval = interval;
    }

    public int getBgColor() {
        return bgColor;
    }

    public void setBgColor(int bgColor) {
        this.bgColor = bgColor;
    }

    public List<String> getX_coord_values() {
        return x_coord_values;
    }
    /**
     * 设置坐标折线图值
     */
    public void  setValue( List<String> x_coords ,List<String> x_coord_values) {
        if(x_coord_values.size()!=x_coords.size()){
            throw new IllegalArgumentException("坐标轴点和坐标轴点的值的个数必须一样!");
        }
        this.x_coord_values=x_coord_values;
        this.x_coords=x_coords;
        invalidate();
    }
}

自定义文件里注释比较详细,就不解释了。
3.布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    xmlns:app="http://schemas.android.com/apk/res/com.dfwy.cxy.lineview">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:id="@+id/tv"
        android:text="拆线图"
        android:textColor="#fff"
        android:gravity="center"
        android:background="@color/colorAccent"
        />
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="1.8dp"
        android:layout_below="@+id/tv"
        android:background="#fff"
        android:id="@+id/iv_lin"
        />
    <com.dfwy.cxy.lineview.LineCharView
        android:id="@+id/test"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:xytextcolor="#fff"
        app:bgcolor="@color/colorAccent"
        app:xytextsize="20sp"
        app:interval="80dp"
        android:layout_below="@+id/iv_lin"
        />
</RelativeLayout>

在这里要注意:
这里写图片描述
不懂的参考这个文章
http://blog.csdn.net/xiaoyu940601/article/details/54894105
最后demo的下载地址:
http://download.csdn.net/detail/xiaoyu940601/9748300
资源下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值