欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Android自定義View--自定義柱狀圖

 更新時(shí)間:2016年12月22日 15:27:50   作者:Hankkin  
這篇文章主要介紹了詳解Android自定義View--自定義柱狀圖,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

緒論

轉(zhuǎn)眼間,2016伴隨著互聯(lián)網(wǎng)寒冬和帝都的霧霾馬上就過(guò)去了,不知道大家今年一整年過(guò)得怎么樣?最近票圈被各個(gè)城市的霧霾刷屏,內(nèi)心難免會(huì)動(dòng)蕩,慶幸自己早出來(lái)一年,也擔(dān)憂著自己的未來(lái)的職業(yè)規(guī)劃。無(wú)所謂了,既然選擇了這個(gè)行業(yè),我覺(jué)得大家就應(yīng)該堅(jiān)持下去,路是自己走的,及時(shí)再寒冬,只要你足夠優(yōu)秀,足夠努力,相信你最后還是會(huì)找到自己滿意的工作的。最后還要感謝今年博客之星大家對(duì)我的投票支持,非常感謝。不多說(shuō)了,今天的主題是它–對(duì),自定義View柱狀圖。

先來(lái)說(shuō)說(shuō)我最近在做什么吧?好久沒(méi)有寫(xiě)博客了,最近手里有兩個(gè)項(xiàng)目,閑的時(shí)候一直在忙著做項(xiàng)目,也封裝了屬于自己的一套Library,抽下來(lái)我會(huì)把它分享出來(lái)的。公司的項(xiàng)目也一直在忙,今天的柱狀圖就是公司的項(xiàng)目所用到的。先來(lái)看一下效果吧

具體實(shí)現(xiàn)

可以看到,今天的柱狀圖分為三類(lèi):雙條豎向柱狀圖、單條豎向柱狀圖以及單條橫向柱狀圖,其實(shí)原理都是一樣的,下面我們具體看一下怎么實(shí)現(xiàn),怎么去畫(huà)一個(gè)這樣的柱狀圖。

雙條豎向

我們可以看到這個(gè)柱狀圖主要包括下面幾個(gè)方面:

  • 雙條柱狀圖
  • 橫坐標(biāo)月份
  • 點(diǎn)擊tips顯示具體數(shù)值
  • 灰色陰影(圖上沒(méi)有顯示具體看代碼)
  • 柱狀圖漸變、圓角、點(diǎn)擊變色

好了上面五點(diǎn)就是需求和UI所提出來(lái)的所有東西,我們開(kāi)始著手去“畫(huà)”吧。

1.首先我們定義一些資源style供使用

包括

  • leftColor 左側(cè)柱狀圖頂部顏色
  • leftColorBottom 左側(cè)柱狀圖底部顏色
  • rightColor 右側(cè)柱狀圖頂部顏色
  • rightColorBottom 右側(cè)柱狀圖底部顏色
  • selectRightColor 左側(cè)點(diǎn)擊選中顏色
  • selectRightColor 右側(cè)點(diǎn)擊選中顏色
  • xyColor 橫軸字體顏色

底部和頂部顏色是用于漸變用的

<declare-styleable name="MyChartView">
    <attr name="leftColor" format="color"></attr>
    <attr name="leftColorBottom" format="color"></attr>
    <attr name="selectLeftColor" format="color"></attr>
    <attr name="rightColor" format="color"></attr>
    <attr name="rightColorBottom" format="color"></attr>
    <attr name="selectRightColor" format="color"></attr>
    <attr name="xyColor" format="color"></attr>
  </declare-styleable>

2.接下來(lái)我們看具體代碼,注釋寫(xiě)的很詳細(xì)了,仔細(xì)看:

  • 初始化屬性、畫(huà)筆、所用的size等
  • 測(cè)量計(jì)算高寬度等
  • 畫(huà)坐標(biāo)軸、畫(huà)月份、畫(huà)柱狀圖、畫(huà)陰影
  • 柱狀圖漸變以及點(diǎn)擊變色
  • touch點(diǎn)擊事件判斷點(diǎn)擊所屬哪個(gè)月份,接口回調(diào)給activity顯示具體月份數(shù)值

注意:onWindowVisibilityChanged這個(gè)方法(當(dāng)屏幕焦點(diǎn)變化時(shí)重新側(cè)向起始位置,必須重寫(xiě)次方法,否則當(dāng)焦點(diǎn)變化時(shí)柱狀圖會(huì)跑到屏幕外面)

下面主要說(shuō)一下繪制部分吧

OnDraw()部分

我們將每次onTouch的條的索引放到selectIndexRoles數(shù)組中,然后當(dāng)這個(gè)數(shù)組包含該繪制的柱狀圖的索引是我們?cè)O(shè)置不用顏色以及不設(shè)置漸變;

同時(shí)我們給每?jī)蓚€(gè)雙條之間的的空白處繪制成陰影;

最后drawRoundRect()就繪制了一個(gè)圓角的矩形。

//畫(huà)柱狀圖
    for (int i = 0; i < list.size(); i++) {
      int size = mHeight / 120;
      if (selectIndexRoles.contains(i)) {
        //偶數(shù)
        mChartPaint.setShader(null);
        if (i % 2 == 0) {
          mChartPaint.setColor(selectLeftColor);
        } else {
          mChartPaint.setColor(selectRightColor);
        }
      } else {
        //偶數(shù)
        if (i % 2 == 0) {
          LinearGradient lg = new LinearGradient(mChartWidth, mChartWidth + mSize, mHeight - 100,
            (float) (mHeight - 100 - list.get(i) * size), lefrColorBottom, leftColor, Shader.TileMode.MIRROR);
          mChartPaint.setShader(lg);
        } else {
          LinearGradient lg = new LinearGradient(mChartWidth, mChartWidth + mSize, mHeight - 100,
            (float) (mHeight - 100 - list.get(i) * size), rightColorBottom, rightColor, Shader.TileMode.MIRROR);
          mChartPaint.setShader(lg);
        }
      }

      mChartPaint.setStyle(Paint.Style.FILL);
      //畫(huà)陰影
      if (i == number * 2 || i == number * 2 + 1) {
        mShadowPaint.setColor(Color.BLUE);
      } else {
        mShadowPaint.setColor(Color.WHITE);
      }

      //畫(huà)柱狀圖
      RectF rectF = new RectF();
      rectF.left = mChartWidth;
      rectF.right = mChartWidth + mSize;
      rectF.bottom = mHeight - 100;
      rectF.top = (float) (mHeight - 100 - list.get(i) * size);
      canvas.drawRoundRect(rectF, 10, 10, mChartPaint);
      //canvas.drawRect(mChartWidth, mHeight - 100 - list.get(i) * size, mChartWidth + mSize, mHeight - 100, mChartPaint)
      // ;// 長(zhǎng)方形
      mChartWidth += (i % 2 == 0) ? (3 + getWidth() / 39) : (getWidth() / 13 - 3 - mSize);
    }

全部代碼

package com.hankkin.mycartdemo.chatview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.hankkin.mycartdemo.R;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Hankkin on 2016/12/10.
 */

public class MyChartView extends View {

  private int leftColor;//雙柱左側(cè)
  private int rightColor;//雙柱右側(cè)
  private int lineColor;//橫軸線
  private int selectLeftColor;//點(diǎn)擊選中左側(cè)
  private int selectRightColor;//點(diǎn)擊選中右側(cè)
  private int lefrColorBottom;//左側(cè)底部
  private int rightColorBottom;//右側(cè)底部
  private Paint mPaint, mChartPaint, mShadowPaint;//橫軸畫(huà)筆、柱狀圖畫(huà)筆、陰影畫(huà)筆
  private int mWidth, mHeight, mStartWidth, mChartWidth, mSize;//屏幕寬度高度、柱狀圖起始位置、柱狀圖寬度
  private Rect mBound;
  private List<Float> list = new ArrayList<>();//柱狀圖高度占比
  private Rect rect;//柱狀圖矩形
  private getNumberListener listener;//點(diǎn)擊接口
  private int number = 1000;//柱狀圖最大值
  private int selectIndex = -1;//點(diǎn)擊選中柱狀圖索引
  private List<Integer> selectIndexRoles = new ArrayList<>();

  public void setList(List<Float> list) {
    this.list = list;
    mSize = getWidth() / 39;
    mStartWidth = getWidth() / 13;
    mChartWidth = getWidth() / 13 - mSize - 3;
    invalidate();
  }

  public void setListener(getNumberListener listener) {
    this.listener = listener;
  }

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

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

  public MyChartView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    //獲取我們自定義的樣式屬性
    TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyChartView, defStyleAttr, 0);
    int n = array.getIndexCount();
    for (int i = 0; i < n; i++) {
      int attr = array.getIndex(i);
      switch (attr) {
        case R.styleable.MyChartView_leftColor:
          // 默認(rèn)顏色設(shè)置為黑色
          leftColor = array.getColor(attr, Color.BLACK);
          break;
        case R.styleable.MyChartView_selectLeftColor:
          // 默認(rèn)顏色設(shè)置為黑色
          selectLeftColor = array.getColor(attr, Color.BLACK);
          break;
        case R.styleable.MyChartView_rightColor:
          rightColor = array.getColor(attr, Color.BLACK);
          break;
        case R.styleable.MyChartView_selectRightColor:
          selectRightColor = array.getColor(attr, Color.BLACK);
          break;
        case R.styleable.MyChartView_xyColor:
          lineColor = array.getColor(attr, Color.BLACK);
          break;
        case R.styleable.MyChartView_leftColorBottom:
          lefrColorBottom = array.getColor(attr, Color.BLACK);
          break;
        case R.styleable.MyChartView_rightColorBottom:
          rightColorBottom = array.getColor(attr, Color.BLACK);
          break;
      }
    }
    array.recycle();
    init();
  }

  //初始化畫(huà)筆
  private void init() {
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mBound = new Rect();
    mChartPaint = new Paint();
    mChartPaint.setAntiAlias(true);
    mShadowPaint = new Paint();
    mShadowPaint.setAntiAlias(true);
    mShadowPaint.setColor(Color.WHITE);
  }

  //測(cè)量高寬度
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width;
    int height;
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);

    if (widthMode == MeasureSpec.EXACTLY) {
      width = widthSize;
    } else {
      width = widthSize * 1 / 2;
    }
    if (heightMode == MeasureSpec.EXACTLY) {
      height = heightSize;
    } else {
      height = heightSize * 1 / 2;
    }

    setMeasuredDimension(width, height);
  }

  //計(jì)算高度寬度
  @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    mWidth = getWidth();
    mHeight = getHeight();
    mStartWidth = getWidth() / 13;
    mSize = getWidth() / 39;
    mChartWidth = getWidth() / 13 - mSize;
  }

  //重寫(xiě)onDraw繪制
  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    mPaint.setColor(lineColor);
    //畫(huà)坐標(biāo)軸
    //canvas.drawLine(0, mHeight - 100, mWidth, mHeight - 100, mPaint);
    for (int i = 0; i < 12; i++) {
      //畫(huà)刻度線
      //canvas.drawLine(mStartWidth, mHeight - 100, mStartWidth, mHeight - 80, mPaint);
      //畫(huà)數(shù)字
      mPaint.setTextSize(35);
      mPaint.setTextAlign(Paint.Align.CENTER);
      mPaint.getTextBounds(String.valueOf(i + 1) + "", 0, String.valueOf(i).length(), mBound);
      canvas.drawText(String.valueOf(i + 1) + "月", mStartWidth - mBound.width() * 1 / 2,
        mHeight - 60 + mBound.height() * 1 / 2, mPaint);
      mStartWidth += getWidth() / 13;
    }
    //畫(huà)柱狀圖
    for (int i = 0; i < list.size(); i++) {
      int size = mHeight / 120;
      if (selectIndexRoles.contains(i)) {
        //偶數(shù)
        mChartPaint.setShader(null);
        if (i % 2 == 0) {
          mChartPaint.setColor(selectLeftColor);
        } else {
          mChartPaint.setColor(selectRightColor);
        }
      } else {
        //偶數(shù)
        if (i % 2 == 0) {
          LinearGradient lg = new LinearGradient(mChartWidth, mChartWidth + mSize, mHeight - 100,
            (float) (mHeight - 100 - list.get(i) * size), lefrColorBottom, leftColor, Shader.TileMode.MIRROR);
          mChartPaint.setShader(lg);
        } else {
          LinearGradient lg = new LinearGradient(mChartWidth, mChartWidth + mSize, mHeight - 100,
            (float) (mHeight - 100 - list.get(i) * size), rightColorBottom, rightColor, Shader.TileMode.MIRROR);
          mChartPaint.setShader(lg);
        }
      }

      mChartPaint.setStyle(Paint.Style.FILL);
      //畫(huà)陰影
      if (i == number * 2 || i == number * 2 + 1) {
        mShadowPaint.setColor(Color.BLUE);
      } else {
        mShadowPaint.setColor(Color.WHITE);
      }

      //畫(huà)柱狀圖
      RectF rectF = new RectF();
      rectF.left = mChartWidth;
      rectF.right = mChartWidth + mSize;
      rectF.bottom = mHeight - 100;
      rectF.top = (float) (mHeight - 100 - list.get(i) * size);
      canvas.drawRoundRect(rectF, 10, 10, mChartPaint);
      //canvas.drawRect(mChartWidth, mHeight - 100 - list.get(i) * size, mChartWidth + mSize, mHeight - 100, mChartPaint)
      // ;// 長(zhǎng)方形
      mChartWidth += (i % 2 == 0) ? (3 + getWidth() / 39) : (getWidth() / 13 - 3 - mSize);
    }
  }

  @Override
  public void onWindowFocusChanged(boolean hasWindowFocus) {
    super.onWindowFocusChanged(hasWindowFocus);
    if (hasWindowFocus) {

    }
  }

  /**
   * 注意:
   * 當(dāng)屏幕焦點(diǎn)變化時(shí)重新側(cè)向起始位置,必須重寫(xiě)次方法,否則當(dāng)焦點(diǎn)變化時(shí)柱狀圖會(huì)跑到屏幕外面
   */

  @Override
  protected void onWindowVisibilityChanged(int visibility) {
    super.onWindowVisibilityChanged(visibility);
    if (visibility == VISIBLE) {
      mSize = getWidth() / 39;
      mStartWidth = getWidth() / 13;
      mChartWidth = getWidth() / 13 - mSize - 3;
    }
  }

  /**
   * 柱狀圖touch事件
   * 獲取觸摸位置計(jì)算屬于哪個(gè)月份的
   * @param ev
   * @return
   */
  @Override
  public boolean onTouchEvent(MotionEvent ev) {

    int x = (int) ev.getX();
    int y = (int) ev.getY();
    int left = 0;
    int top = 0;
    int right = mWidth / 12;
    int bottom = mHeight - 100;
    switch (ev.getAction()) {
      case MotionEvent.ACTION_DOWN:
        for (int i = 0; i < 12; i++) {
          rect = new Rect(left, top, right, bottom);
          left += mWidth / 12;
          right += mWidth / 12;
          if (rect.contains(x, y)) {
            listener.getNumber(i, x, y);
            number = i;
            selectIndex = i;
            selectIndexRoles.clear();
            ;
            selectIndexRoles.add(selectIndex * 2 + 1);
            selectIndexRoles.add(selectIndex * 2);
            invalidate();
          }
        }
        break;
      case MotionEvent.ACTION_UP:

        break;
    }
    return true;
  }

  public interface getNumberListener {
    void getNumber(int number, int x, int y);
  }

  public int getLeftColor() {
    return leftColor;
  }

  public void setLeftColor(int leftColor) {
    this.leftColor = leftColor;
  }

  public int getRightColor() {
    return rightColor;
  }

  public void setRightColor(int rightColor) {
    this.rightColor = rightColor;
  }

  public int getLineColor() {
    return lineColor;
  }

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

  public int getSelectLeftColor() {
    return selectLeftColor;
  }

  public void setSelectLeftColor(int selectLeftColor) {
    this.selectLeftColor = selectLeftColor;
  }

  public int getSelectRightColor() {
    return selectRightColor;
  }

  public void setSelectRightColor(int selectRightColor) {
    this.selectRightColor = selectRightColor;
  }

  public int getLefrColorBottom() {
    return lefrColorBottom;
  }

  public void setLefrColorBottom(int lefrColorBottom) {
    this.lefrColorBottom = lefrColorBottom;
  }

  public int getRightColorBottom() {
    return rightColorBottom;
  }

  public void setRightColorBottom(int rightColorBottom) {
    this.rightColorBottom = rightColorBottom;
  }
}

3.具體使用:

private void initChatView() {

    myChartView.setLefrColorBottom(getResources().getColor(R.color.leftColorBottom));
    myChartView.setLeftColor(getResources().getColor(R.color.leftColor));
    myChartView.setRightColor(getResources().getColor(R.color.rightColor));
    myChartView.setRightColorBottom(getResources().getColor(R.color.rightBottomColor));
    myChartView.setSelectLeftColor(getResources().getColor(R.color.selectLeftColor));
    myChartView.setSelectRightColor(getResources().getColor(R.color.selectRightColor));
    myChartView.setLineColor(getResources().getColor(R.color.xyColor));
    chartList = new ArrayList<>();

    relativeLayout = (RelativeLayout) findViewById(R.id.linearLayout);
    relativeLayout.removeView(llChart);
    Random random = new Random();
    while (chartList.size() < 24) {
      int randomInt = random.nextInt(100);
      chartList.add((float) randomInt);
    }
    myChartView.setList(chartList);
    myChartView.setListener(new MyChartView.getNumberListener() {
      @Override
      public void getNumber(int number, int x, int y) {
        relativeLayout.removeView(llChart);
        //反射加載點(diǎn)擊柱狀圖彈出布局
        llChart = (LinearLayout) LayoutInflater.from(MainActivity.this).inflate(R.layout.layout_shouru_zhichu, null);
        TextView tvZhichu = (TextView) llChart.findViewById(R.id.tv_zhichu);
        TextView tvShouru = (TextView) llChart.findViewById(R.id.tv_shouru);
        tvZhichu.setText((number + 1) + "月支出" + " " + chartList.get(number * 2));
        tvShouru.setText ( "收入: " + chartList.get(number * 2 + 1));
        llChart.measure(0, 0);//調(diào)用該方法后才能獲取到布局的寬度
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
          RelativeLayout.LayoutParams.WRAP_CONTENT);
        params.leftMargin = x - 100;
        if (x - 100 < 0) {
          params.leftMargin = 0;
        } else if (x - 100 > relativeLayout.getWidth() - llChart.getMeasuredWidth()) {
          //設(shè)置布局距左側(cè)屏幕寬度減去布局寬度
          params.leftMargin = relativeLayout.getWidth() - llChart.getMeasuredWidth();
        }
        llChart.setLayoutParams(params);
        relativeLayout.addView(llChart);
      }
    });
  }

經(jīng)過(guò)以上步驟,我們的雙條豎向柱狀圖就繪制完成了,也顯示出來(lái)了。其實(shí)自己坐下來(lái)仔細(xì)拿筆算一下,畫(huà)一下,也沒(méi)有想象的那么難。至于單條和橫向的實(shí)現(xiàn)原理都一樣,比這個(gè)要簡(jiǎn)單的多。哦對(duì)了,橫向的我只是自定義了一個(gè)橫向的柱狀圖View,然后用ListView顯示的各個(gè)部門(mén)的具體內(nèi)容。

代碼下載:demo

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論