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

首頁 > 系統 > Android > 正文

Android自定義帶增長動畫和點擊彈窗提示效果的柱狀圖DEMO

2019-12-12 04:44:44
字體:
來源:轉載
供稿:網友

項目中最近用到各種圖表,本來打算用第三方的,例如MPAndroid,這是一個十分強大的圖表庫,應用起來十分方便,但是最終發現和設計不太一樣,沒辦法,只能自己寫了。今天將寫好的柱狀圖的demo貼在這,該柱狀圖可根據數據的功能有一下幾點:

     1. 根據數據的多少,動態的繪制柱狀圖柱子的條數;

     2. 柱狀圖每條柱子的繪制都有動態的動畫效果;

     3. 每條柱子有點擊事件,點擊時彈出提示框,顯示相關信息,規定時間后,彈窗自動消失。

     好了,先上演示圖:

     下邊貼出相關代碼:

     自定義柱狀圖類:

package com.example.histogram; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.os.Handler; import android.text.TextPaint; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import com.example.histogram.UI.UI; import java.text.NumberFormat; /**  * Created by ZHANGZDon 2016/6/16 0016.  * 柱狀圖  */ public class HistoGram extends View implements Runnable {   private Handler handler = new Handler(); // 用于延時更新,實現動畫   private float animHeight; // 進度條動畫高度   private Paint axisLinePaint; // 坐標軸畫筆   private Paint hLinePaint; // 內部水平虛線畫筆   private Paint textPaint; // 繪制文本的畫筆   private Paint recPaint; // 繪制柱狀圖陰影背景的畫筆   private Paint dataPaint; // 繪制柱狀圖的畫筆   private Paint textPaint2; // 繪制白色文本的畫筆   private Paint textPaint3; // 繪制坐標的畫筆   private Paint textPaint4; // 繪制x軸上的白色豎線的畫筆   private String[] xTitleString; // x軸刻度   private String[] yTitleString; // y軸刻度   private String[] data; // 接口返回的indicatordata,用于計算柱子高度   NumberFormat numberFormat; //用于格式化數字   private float currentHeight; // 當前柱狀圖應有的高度,應由計算得來   private int num = -1; // 畫多少條柱子,因為存在剛開機數據不足24條的情況   private float mRelativePxInHeight;   private float mRelativePxInWidth;   private OnChartClickListener listener;   private int mDist;   public void setNum(int num) {     this.num = num;     invalidate();   }   public void setData(String[] data) {     this.data = data;     invalidate();   }   public void setxTitleString(String[] title) {     this.xTitleString = title;     invalidate();   }   public HistoGram(Context context) {     this(context, null);   }   public HistoGram(Context context, AttributeSet attrs) {     this(context, attrs, 0);   }   public void setTitle(String[] title) {     this.xTitleString = title;   }   public HistoGram(Context context, AttributeSet attrs, int defStyleAttr) {     super(context, attrs, defStyleAttr);     init(context, attrs);   }   /**    * 進行相關初始化操作    * @param context    * @param attrs    */   private void init(Context context, AttributeSet attrs) {     axisLinePaint = new Paint();     hLinePaint = new Paint();     textPaint = new Paint();     recPaint = new Paint();     dataPaint = new Paint();     textPaint2 = new Paint();     textPaint3 = new Paint();     textPaint4 = new Paint();     numberFormat = NumberFormat.getNumberInstance();     numberFormat.setMinimumFractionDigits(3); //設置打印時保留三位小數     axisLinePaint.setColor(Color.parseColor("#dbdde4")); //設置坐標軸的顏色為白色     hLinePaint.setARGB(51, 255, 255, 255);     textPaint.setColor(Color.parseColor("#8593a1")); //    textPaint.setTextSize(29);     textPaint.setTextSize(UI.dip2px(getContext(), 12));     recPaint.setColor(Color.parseColor("#f2f5fc"));     dataPaint.setColor(Color.CYAN);     textPaint2.setColor(Color.WHITE);     textPaint2.setTextSize(UI.dip2px(getContext(), 12));     textPaint3.setColor(Color.parseColor("#000000"));     textPaint3.setTextSize(UI.dip2px(getContext(), 9));     textPaint4.setColor(Color.parseColor("#8593a1"));     textPaint4.setTextSize(UI.dip2px(getContext(), 6));     axisLinePaint.setAntiAlias(true);     hLinePaint.setAntiAlias(true);     textPaint.setAntiAlias(true);     recPaint.setAntiAlias(true);     dataPaint.setAntiAlias(true);     textPaint2.setAntiAlias(true);     textPaint3.setAntiAlias(true);     textPaint4.setAntiAlias(true);   }   @Override   protected void onDraw(Canvas canvas) {     super.onDraw(canvas);     if(data == null || xTitleString == null || num < 0 ) {       return;     }     //繪制y軸刻度     Paint.FontMetrics metrics = textPaint3.getFontMetrics();     int decent = (int) metrics.descent;     float width = getWidth();     float height = getHeight();     //根據原型圖得出,圖中每px高度在實際中的相對尺寸     mRelativePxInHeight = height / 470;     //根據原型圖得出,圖中每px寬度在實際中的相對尺寸     mRelativePxInWidth = width / 690;     textPaint3.setTextAlign(Paint.Align.RIGHT);     //繪制縱坐標     yTitleString = new String[6];     yTitleString[5] = "0";     yTitleString[4] = "20";     yTitleString[3] = "40";     yTitleString[2] = "60";     yTitleString[1] = "80";     yTitleString[0] = "100";     for (int i = 0; i < yTitleString.length; i++) {       canvas.drawText(yTitleString[i], 88 * mRelativePxInWidth, (72 + i * 56) * mRelativePxInHeight + decent, textPaint3);     }     //繪制x軸刻度     textPaint3.setTextAlign(Paint.Align.CENTER);     textPaint4.setTextAlign(Paint.Align.CENTER);     TextPaint textPaint = new TextPaint();     textPaint.setColor(Color.parseColor("#000000"));     textPaint.setTextSize(UI.dip2px(getContext(), 9));     //計算柱子之間的間隔     //最左側位置100 * mRelativePxInWidth,最右側位置630 ePxInWidth,     float totalWidth = 630 - 100;     // 柱子與之子之間的間隔     mDist = (int) (totalWidth / (xTitleString.length + 1));     for (int i = 0; i < xTitleString.length; i++) {       //繪制白色豎線       canvas.drawLine((100 + (i+1) * mDist) * mRelativePxInWidth, 348 * mRelativePxInHeight, (100 + (i+1) * mDist) * mRelativePxInWidth, 352 * mRelativePxInHeight, axisLinePaint);       //繪制x軸文字       canvas.drawText(xTitleString[i], (100 + (i+1) * mDist) * mRelativePxInWidth, 370 * mRelativePxInHeight, textPaint3);     } //    繪制矩形陰影     for (int i = 0; i < num; i++) {       RectF rectF = new RectF(); //      rectF.left = 111 * relativePxInWidth + i * 22 * relativePxInWidth; //      rectF.right = 121 * relativePxInWidth + i * 22 * relativePxInWidth;       rectF.left = 95 * mRelativePxInWidth + (i+1) * mDist * mRelativePxInWidth;       rectF.right = 105 * mRelativePxInWidth +(i+1) * mDist * mRelativePxInWidth;       rectF.top = 70 * mRelativePxInHeight;       rectF.bottom = 338 * mRelativePxInHeight;       canvas.drawRoundRect(rectF, 10, 10, recPaint);     }     //    繪制x軸坐標線     for (int i = 0; i < 6; i++) {       canvas.drawLine(100 * mRelativePxInWidth, (66 + i * 56) * mRelativePxInHeight + decent, 630 * mRelativePxInWidth, (66 + i * 56) * mRelativePxInHeight + decent, axisLinePaint);     } //    延時繪制,實現動畫效果。數字越大,延時越久,動畫效果就會越慢     handler.postDelayed(this, 1);     for (int i = 0; i < num; i++) {       RectF dataRectF = new RectF();       dataRectF.left = 95 * mRelativePxInWidth + (i + 1) * mDist * mRelativePxInWidth;       dataRectF.right = 105 * mRelativePxInWidth + (i + 1) * mDist * mRelativePxInWidth;       dataPaint.setColor(Color.parseColor("#3ac2d9"));       //獲取柱子高度       currentHeight = Float.parseFloat(data[num - 1 - i]);       if (currentHeight == 0) {         dataRectF.top = 346 * mRelativePxInHeight;       } else if (currentHeight == 100) {         dataRectF.top = 70 * mRelativePxInHeight;       } else {         if (animHeight >= currentHeight) {           dataRectF.top = 346 * mRelativePxInHeight - currentHeight / 100 * 276 * mRelativePxInHeight;         } else {           dataRectF.top = 346 * mRelativePxInHeight - 276 * mRelativePxInHeight * (animHeight / 100);         }       }       dataRectF.bottom = 346 * mRelativePxInHeight; //        限制最高高度       if (dataRectF.top < 70 * mRelativePxInHeight) {         dataRectF.top = 70 * mRelativePxInHeight;       }       canvas.drawRoundRect(dataRectF, 10, 10, dataPaint);     }   }   //實現柱子增長的動畫效果   @Override   public void run() {     animHeight += 1;     if (animHeight >= 276 * mRelativePxInHeight) {       return;     } else {       invalidate();     }   }   @Override   public boolean onTouchEvent(MotionEvent event) {     switch (event.getAction()) {       case MotionEvent.ACTION_DOWN: {         //獲取點擊坐標         float x = event.getX();         float y = event.getY();         //判斷點擊點的位置         float leftx = 0;         float rightx = 0;         for (int i = 0; i < num; i++) {           leftx = 95 * mRelativePxInWidth + (i+ 1) * mDist * mRelativePxInWidth - mDist/2 * mRelativePxInWidth;           rightx = 105 * mRelativePxInWidth + (i+ 1) * mDist * mRelativePxInWidth + mDist/2 * mRelativePxInWidth;           if (x < leftx) {             continue;           }           if (leftx <= x && x <= rightx) {             //獲取點擊的柱子區域的y值             float top = 346 * mRelativePxInHeight - Float.parseFloat(data[num - 1 - i])/ 100 * 276 * mRelativePxInHeight;             float bottom = 346 * mRelativePxInHeight;             if (y >= top && y <= bottom) {               //判斷是否設置監聽               //將點擊的第幾條柱子,點擊柱子頂部的坐值,用于彈出dialog提示數據,還要返回百分比currentHeidht = Float.parseFloat(data[num - 1 - i])               if(listener != null) {                 Log.e("ss","x" + x +";y:" + y);                 listener.onClick(i + 1, leftx + mDist/2,top,Float.parseFloat(data[num - 1 - i]));               }               break;             }           }         }         break;       }       case MotionEvent.ACTION_MOVE:         Log.e("touch", "ACTION_MOVE");         break;       case MotionEvent.ACTION_UP:         Log.e("touch", "ACTION_UP");         break;     }     return true;   }   /**    * 柱子點擊時的監聽接口    */   public interface OnChartClickListener {     void onClick(int num, float x, float y, float value);   }   /**    * 設置柱子點擊監聽的方法    * @param listener    */   public void setOnChartClickListener(OnChartClickListener listener) {     this.listener = listener;   } } 

  在xml文件中的應用:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout   xmlns:android="http://schemas.android.com/apk/res/android"   xmlns:tools="http://schemas.android.com/tools"   android:id="@+id/activity_main"   android:layout_width="match_parent"   android:layout_height="match_parent"   android:orientation="vertical"   tools:context="com.example.histogram.MainActivity">   <TextView     android:layout_width="match_parent"     android:layout_height="40dp"     android:gravity="center"     android:text="繁忙度指示圖(%)"     android:textSize="15sp"     android:textColor="#000000"     />   <com.example.histogram.HistoGram     android:id="@+id/staticview"     android:layout_width="400dp"     android:layout_height="500dp"     android:layout_gravity="center_horizontal"     android:layout_marginBottom="14dp"     android:layout_marginTop="5dp"/> </LinearLayout> 

   在activity中的實現:

package com.example.histogram; import android.os.Bundle; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.PopupWindow; import android.widget.TextView; public class MainActivity extends AppCompatActivity {   private PopupWindow mPopupWindow;   @Override   protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_main);     final HistoGram histoGram = (HistoGram) findViewById(R.id.staticview);     String[] data ={"100","20","40","20","80","20","60","30","5","20","60","30","5","5","20","60","30","5"};     final String[] title = {"1","2","3","4","5","6","7","8","9","6","7","8","9","9","6","7","8","9"};     histoGram.setNum(title.length);     histoGram.setData(data);     histoGram.setxTitleString(title);     histoGram.setOnChartClickListener(new HistoGram.OnChartClickListener() {       @Override       public void onClick(int num, float x, float y, float value) {         //顯示提示窗         View inflate = View.inflate(MainActivity.this, R.layout.popupwindow, null);         TextView textView = (TextView) inflate.findViewById(R.id.main_tv);         textView.setText(value + "%/n" + title[num - 1]);         if(mPopupWindow != null) {           mPopupWindow.dismiss();         }         mPopupWindow = new PopupWindow(inflate,140, 60, true);         mPopupWindow.setTouchable(true);         Log.e("ss","num" + num +";x" + x+";y"+ y + ";value" + value             +";(int)((- histoGram.getHeight()) + y - 65)"             +(int)((- histoGram.getHeight()) + y - 65)         + "histoGram.getHeight()" + histoGram.getHeight());         // 設置好參數之后再show //        Toast.makeText(MainActivity.this, "num" + num +";x" + x+";y"+ y + ";value" + value //            +";popupWindow.getWidth()"+ mPopupWindow.getWidth()+";"+ mPopupWindow.getHeight(), Toast.LENGTH_SHORT).show();         mPopupWindow.showAsDropDown(histoGram,(int)(x - 65),(int)((- histoGram.getHeight()) + y - 65) );         mPopupWindow.setBackgroundDrawable(getResources().getDrawable(R.mipmap.databg_busyness));         new Handler().postDelayed(new Runnable(){           public void run() {             mPopupWindow.dismiss();           }         }, 1000);       }     });   } } 

以上所述是小編給大家介紹的Android自定義帶增長動畫和點擊彈窗提示效果的柱狀圖,實現一個模擬后臺數據登入的效果,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 平乡县| 闽侯县| 台北县| 海晏县| 永兴县| 加查县| 玉溪市| 南溪县| 鄂尔多斯市| 永春县| 鄂州市| 尼玛县| 芮城县| 孟州市| 钟祥市| 常德市| 竹溪县| 潢川县| 铜山县| 东莞市| 台东县| 莎车县| 宁武县| 鹤庆县| 宜章县| 和田市| 日喀则市| 赫章县| 牙克石市| 江孜县| 大竹县| 罗城| 靖宇县| 罗甸县| 兴业县| 南昌县| 北京市| 鄂州市| 郁南县| 贡嘎县| 南和县|