国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android自定義控件(實現(xiàn)狀態(tài)提示圖表)

2019-12-12 04:48:42
字體:
供稿:網(wǎng)友

前面分析那么多系統(tǒng)源碼了,也該暫停下來休息一下,趁昨晚閑著看見一個有意思的需求就操練一下分析源碼后的實例演練―-自定義控件。

這個實例很適合新手入門自定義控件。先看下效果圖:

橫屏模式如下:
豎屏模式如下:

看見沒有,這個控件完全自定義的,連文字等都是自定義的,沒有任何圖片等資源,就僅僅是一個小的Java文件,這個界面只有一個控件。如下咱們看下實現(xiàn)代碼。

實例代碼

如下就是整個工程的源碼了。

自定義上面展示的控件AreaChartsView源碼:

/** * Author    : yanbo * Date     : 2015-06-03 * Time     : 09:22 * Description : 自定義區(qū)域描述圖表View */public class AreaChartsView extends View {  private Paint mPaint;  private int[] mZeroPos = new int[2];  private int[] mMaxYPos = new int[2];  private int[] mMaxXPos = new int[2];  private int mWidth, mHight;  private int mRealWidth, mRealHight;  private String mTitleY, mTitleX;  private ArrayList<Integer> mXLevel = new ArrayList<>();  private ArrayList<Integer> mYLevel = new ArrayList<>();  private ArrayList<String> mGridLevelText = new ArrayList<>();  private ArrayList<Integer> mGridColorLevel = new ArrayList<>();  private ArrayList<Integer> mGridTxtColorLevel = new ArrayList<>();  private int mGridLevel = mXLevel.size() - 1;  //title字符大小  private int mXYTitleTextSize = 40;  private int mMeasureXpos, mMeasureYpos;  public AreaChartsView(Context context, AttributeSet attrs) {    super(context, attrs);    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);    mPaint.setAntiAlias(true);    mPaint.setFilterBitmap(true);  }  @Override  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {    super.onLayout(changed, left, top, right, bottom);    mWidth = getWidth();    mHight = getHeight();  }  @Override  protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    initPosition();    drawXYTitle(canvas);    drawXYLine(canvas);    drawContent(canvas);  }  private void initPosition() {    //初始化坐標圖的xy交點原點坐標    mZeroPos[0] = mXYTitleTextSize * 2;    mZeroPos[1] = mHight - mXYTitleTextSize * 4;    //初始化坐標圖的X軸最大值坐標    mMaxXPos[0] = mWidth;    mMaxXPos[1] = mHight - mXYTitleTextSize * 4;    //初始化坐標圖的Y軸最大值坐標    mMaxYPos[0] = mXYTitleTextSize * 2;    mMaxYPos[1] = mXYTitleTextSize * 2;  }  private void drawXYTitle(Canvas canvas) {    mPaint.setColor(Color.parseColor("#1FB0E7"));    mPaint.setTextSize(mXYTitleTextSize);    mPaint.setTextAlign(Paint.Align.LEFT);    //畫Y軸頂?shù)膖itle    canvas.drawText(mTitleY, mMaxYPos[0] - mXYTitleTextSize * 2, mMaxYPos[1] - mXYTitleTextSize, mPaint);    mPaint.setTextAlign(Paint.Align.RIGHT);    //畫X軸頂?shù)膖itle    canvas.drawText(mTitleX, mMaxXPos[0], mMaxXPos[1] + mXYTitleTextSize * 2, mPaint);  }  private void drawXYLine(Canvas canvas) {    mPaint.setColor(Color.DKGRAY);    mPaint.setTextAlign(Paint.Align.RIGHT);    //畫XY軸    canvas.drawLine(mMaxYPos[0], mMaxYPos[1], mZeroPos[0], mZeroPos[1], mPaint);    canvas.drawLine(mZeroPos[0], mZeroPos[1], mMaxXPos[0], mMaxXPos[1], mPaint);  }  private void drawContent(Canvas canvas) {    mGridLevel = mXLevel.size() - 1;    //計算出偏移title等顯示尺標后的真實XY軸長度,便于接下來等分    mRealWidth = (mWidth - mXYTitleTextSize * 2);    mRealHight = (mHight - mXYTitleTextSize * 4);    //算出等分間距    int offsetX = mRealWidth/(mGridLevel);    int offsetY = mRealHight/(mGridLevel+1);    //循環(huán)繪制content    for (int index=0; index<mGridLevel+1; index++) {      mPaint.setColor(Color.DKGRAY);      mPaint.setTextAlign(Paint.Align.RIGHT);      mPaint.setTextSize(mXYTitleTextSize-5);      //繪制X軸的那些坐標區(qū)間點,包含0點坐標      canvas.drawText(String.valueOf(mXLevel.get(index)), mZeroPos[0]+(index*offsetX), mZeroPos[1] + mXYTitleTextSize, mPaint);      if (index != 0) {        //繪制Y軸坐標區(qū)間點,不包含0點坐標,X軸已經(jīng)畫過了        canvas.drawText(String.valueOf(mYLevel.get(index)), mZeroPos[0], mZeroPos[1]-(index*offsetY), mPaint);      }      if (index == mGridLevel) {        //坐標區(qū)間 = 真實區(qū)間 + 1        break;      }      mPaint.setColor(mGridColorLevel.get(mGridLevel - 1 - index));      mPaint.setStyle(Paint.Style.FILL);      //繪制區(qū)間疊加圖譜方塊,從遠到0坐標,因為小的圖會覆蓋大的圖      canvas.drawRect(mMaxYPos[0], mMaxYPos[1] + index*offsetY, mMaxXPos[0]-index*offsetX, mMaxXPos[1], mPaint);      mPaint.setColor(mGridTxtColorLevel.get(index));      mPaint.setTextAlign(Paint.Align.RIGHT);      mPaint.setTextSize(mXYTitleTextSize);      //繪制每個方塊狀態(tài)區(qū)間的提示文字      canvas.drawText(mGridLevelText.get(index), mMaxXPos[0] - index * offsetX - mXYTitleTextSize,          mMaxYPos[1] + index * offsetY + mXYTitleTextSize, mPaint);    }    //繪制當(dāng)前坐標    drawNotice(canvas, offsetX, offsetY);  }  private void drawNotice(Canvas canvas, int offsetX, int offsetY) {    int realPosX = 0;    int realPosY = 0;    //計算傳入的x值與真實屏幕坐標的像素值的百分比差值轉(zhuǎn)換    for (int index=0; index<mGridLevel; index++) {      if (mMeasureXpos >= mXLevel.get(index) && mMeasureXpos < mXLevel.get(index+1)) {        int subValue = mMeasureXpos - mXLevel.get(index);        int offset = mXLevel.get(index+1) - mXLevel.get(index);        realPosX = mZeroPos[0] + index*offsetX + (subValue / offset);        break;      }    }    //計算傳入的y值與真實屏幕坐標的像素值的百分比差值轉(zhuǎn)換    for (int index=0; index<mGridLevel; index++) {      if (mMeasureYpos >= mYLevel.get(index) && mMeasureYpos < mYLevel.get(index+1)) {        int subValue = mMeasureYpos - mYLevel.get(index);        int offset = mYLevel.get(index+1) - mYLevel.get(index);        realPosY = mZeroPos[1] - index*offsetY - (offsetY - (subValue / offset));        break;      }    }    //畫我們傳入的坐標點的標記小紅點    mPaint.setColor(Color.RED);    mPaint.setStyle(Paint.Style.FILL);    canvas.drawCircle(realPosX, realPosY, 8, mPaint);    int[] centerPos = {mZeroPos[0] + mRealWidth/2, mZeroPos[1] - mRealHight/2};    mPaint.setColor(Color.WHITE);    mPaint.setStyle(Paint.Style.FILL_AND_STROKE);    RectF rectF = null;    Path path = new Path();    //畫紅點旁邊的提示框和文字,有四個區(qū)域,然后提示框的小三角指標方位不同    if (realPosX <= centerPos[0] && realPosY >= centerPos[1]) {      //left-bottom      //畫三角形      path.moveTo(realPosX+5, realPosY+5);      path.lineTo(realPosX+15, realPosY+15);      path.lineTo(realPosX+15, realPosY-15);      //畫矩形背景      rectF = new RectF(realPosX+15, realPosY-40, realPosX+200, realPosY + 30);      canvas.drawRoundRect(rectF, 15, 15, mPaint);      //畫提示框的文字      mPaint.reset();      mPaint.setColor(Color.RED);      mPaint.setTextSize(mXYTitleTextSize - 5);      canvas.drawText("("+mMeasureXpos+", "+mMeasureYpos+")", realPosX+30, realPosY, mPaint);    }    else if (realPosX <= centerPos[0] && realPosY < centerPos[1]) {      //left-top      path.moveTo(realPosX+5, realPosY+5);      path.lineTo(realPosX+15, realPosY+15);      path.lineTo(realPosX + 15, realPosY - 15);      rectF = new RectF(realPosX+15, realPosY - 20, realPosX+200, realPosY + 50);      canvas.drawRoundRect(rectF, 15, 15, mPaint);      mPaint.reset();      mPaint.setColor(Color.RED);      mPaint.setTextSize(mXYTitleTextSize - 5);      canvas.drawText("("+mMeasureXpos+", "+mMeasureYpos+")", realPosX+30, realPosY+20, mPaint);    }    else if (realPosX > centerPos[0] && realPosY >= centerPos[1]) {      //right-bottom      path.moveTo(realPosX-5, realPosY+5);      path.lineTo(realPosX-15, realPosY+15);      path.lineTo(realPosX - 15, realPosY - 15);      rectF = new RectF(realPosX-200, realPosY-40, realPosX-15, realPosY + 30);      canvas.drawRoundRect(rectF, 15, 15, mPaint);      mPaint.reset();      mPaint.setColor(Color.RED);      mPaint.setTextSize(mXYTitleTextSize - 5);      canvas.drawText("("+mMeasureXpos+", "+mMeasureYpos+")", realPosX-180, realPosY, mPaint);    }    else if (realPosX > centerPos[0] && realPosY < centerPos[1]) {      //right-top      path.moveTo(realPosX-5, realPosY+5);      path.lineTo(realPosX-15, realPosY+15);      path.lineTo(realPosX - 15, realPosY - 15);      rectF = new RectF(realPosX-200, realPosY - 20, realPosX-15, realPosY + 50);      canvas.drawRoundRect(rectF, 15, 15, mPaint);      mPaint.reset();      mPaint.setColor(Color.RED);      mPaint.setTextSize(mXYTitleTextSize - 5);      canvas.drawText("("+mMeasureXpos+", "+mMeasureYpos+")", realPosX-180, realPosY+30, mPaint);    }    path.close();    mPaint.setColor(Color.WHITE);    mPaint.setStyle(Paint.Style.FILL_AND_STROKE);    canvas.drawPath(path, mPaint);  }  //設(shè)置當(dāng)前比值  public void updateValues(int x, int y) {    mMeasureXpos = x;    mMeasureYpos = y;    postInvalidate();  }  //設(shè)置XY軸頂角的title字體大小  public void setTitleTextSize(int size) {    mXYTitleTextSize = size;  }  //初始化X軸的坐標區(qū)間點值,可以不均等分  public void initXLevelOffset(ArrayList<Integer> list) {    mXLevel.clear();    mXLevel.addAll(list);  }  //初始化Y軸的坐標區(qū)間點值,可以不均等分  public void initYLevelOffset(ArrayList<Integer> list) {    mYLevel.clear();    mYLevel.addAll(list);  }  //初始化每個區(qū)間的提示文字,如果不想顯示可以設(shè)置""  public void initGridLevelText(ArrayList<String> list) {    mGridLevelText.clear();    mGridLevelText.addAll(list);  }  //初始化每個區(qū)間的顏色  public void initGridColorLevel(ArrayList<Integer> list) {    mGridColorLevel.clear();    mGridColorLevel.addAll(list);  }  //初始化每個區(qū)間的提示文字顏色  public void initGridTxtColorLevel(ArrayList<Integer> list) {    mGridTxtColorLevel.clear();    mGridTxtColorLevel.addAll(list);  }  //初始化XY軸title  public void initTitleXY(String x, String y) {    mTitleX = x;    mTitleY = y;  }}

再來看下布局文件:

<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">  <com.yanbober.customerviewdemo.areachartsview.AreaChartsView    android:id="@+id/area_charts_view"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:layout_margin="10dp"/></RelativeLayout>

再看看主界面:

public class MainActivity extends AppCompatActivity {  private AreaChartsView mAreaChartsView;  private Timer timer;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    mAreaChartsView = (AreaChartsView) this.findViewById(R.id.area_charts_view);    //初始化自定義圖表的規(guī)格和屬性    ArrayList<Integer> mXLevel = new ArrayList<>();    ArrayList<Integer> mYLevel = new ArrayList<>();    ArrayList<String> mGridLevelText = new ArrayList<>();    ArrayList<Integer> mGridColorLevel = new ArrayList<>();    ArrayList<Integer> mGridTxtColorLevel = new ArrayList<>();    //初始化x軸坐標區(qū)間    mXLevel.add(0);    mXLevel.add(60);    mXLevel.add(90);    mXLevel.add(100);    mXLevel.add(110);    mXLevel.add(120);    //初始化y軸坐標區(qū)間    mYLevel.add(0);    mYLevel.add(90);    mYLevel.add(140);    mYLevel.add(160);    mYLevel.add(180);    mYLevel.add(200);    //初始化區(qū)間顏色    mGridColorLevel.add(Color.parseColor("#1FB0E7"));    mGridColorLevel.add(Color.parseColor("#4FC7F4"));    mGridColorLevel.add(Color.parseColor("#4FDDF2"));    mGridColorLevel.add(Color.parseColor("#90E9F4"));    mGridColorLevel.add(Color.parseColor("#B2F6F1"));    //初始化區(qū)間文字提示顏色    mGridTxtColorLevel.add(Color.parseColor("#EA8868"));    mGridTxtColorLevel.add(Color.parseColor("#EA8868"));    mGridTxtColorLevel.add(Color.parseColor("#EA8868"));    mGridTxtColorLevel.add(Color.WHITE);    mGridTxtColorLevel.add(Color.BLACK);    //初始化區(qū)間文字    mGridLevelText.add("異常");    mGridLevelText.add("過高");    mGridLevelText.add("偏高");    mGridLevelText.add("正常");    mGridLevelText.add("偏低");    mAreaChartsView.initGridColorLevel(mGridColorLevel);    mAreaChartsView.initGridLevelText(mGridLevelText);    mAreaChartsView.initGridTxtColorLevel(mGridTxtColorLevel);    mAreaChartsView.initXLevelOffset(mXLevel);    mAreaChartsView.initYLevelOffset(mYLevel);    mAreaChartsView.initTitleXY("投入量(H)", "產(chǎn)出量(H)");  }  @Override  protected void onStart() {    super.onStart();    timer = new Timer();    timer.schedule(new TimerTask() {      @Override      public void run() {        Random random = new Random();        int x = random.nextInt(120) % (120 + 1) + 0;        Random randomy = new Random();        int y = randomy.nextInt(200) % (200 + 1) + 0;        //隨機模擬賦值        mAreaChartsView.updateValues(x, y);      }    }, 0, 1000);  }  @Override  protected void onPause() {    super.onPause();    timer.cancel();  }}

總結(jié)

上面代碼很簡單,核心的都已經(jīng)注釋了,不需要過多解釋。核心思路就是一些坐標點的計算。該控件支持設(shè)置mergin及width與hight等屬性,支持自定義所有顏色及顯示及坐標區(qū)分等,唯一缺陷就是沒來得及寫attr屬性xml設(shè)置這些值,有興趣的自己實現(xiàn)吧,我是沒時間了。

可以發(fā)現(xiàn),自定義View無非就是重寫前面文章分析的那三個方法而已。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 浠水县| 高尔夫| 依安县| 安吉县| 赞皇县| 丰原市| 山阴县| 乐亭县| 莫力| 略阳县| 平乐县| 渭南市| 闸北区| 田林县| 丹巴县| 八宿县| 林周县| 简阳市| 兴业县| 莱阳市| 广汉市| 田阳县| 合肥市| 钟山县| 神木县| 磐安县| 英吉沙县| 廉江市| 秦皇岛市| 桑植县| 甘孜| 阿尔山市| 沈阳市| 肥西县| 阿巴嘎旗| 宝坻区| 营山县| 吕梁市| 沙田区| 泗洪县| 阳春市|