標籤:android canvas
BrokenLine控制項:
import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Calendar;import java.util.Collections;import java.util.Date;import java.util.GregorianCalendar;import java.util.List;import android.content.Context;import android.content.res.Resources;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.DashPathEffect;import android.graphics.LinearGradient;import android.graphics.Paint;import android.graphics.Path;import android.graphics.PathEffect;import android.graphics.Shader;import android.util.Log;import android.view.View;import android.view.ViewGroup.LayoutParams;import com.qianhua.healthy_brain.R;/** * 線框圖 * * @author Administrator * */public class BrokenLine extends View {private List<Integer> milliliter;private float tb;private float interval_left_right;private float interval_left;private float margin_bottom;private Paint paint_date, paint_brokenLine, paint_dottedline,paint_brokenline_big, framPanint;private int time_index;private Bitmap bitmap_point;private Path path;private float dotted_text;public float getDotted_text() {return dotted_text;}public void setDotted_text(float dotted_text) {this.dotted_text = dotted_text;}private int fineLineColor = 0x5faaaaaa; // 灰色private int blueLineColor = 0xff00ffff; // 藍色private int orangeLineColor = 0xffd56f2b; // 橙色public BrokenLine(Context context, List<Integer> milliliter) {super(context);init(milliliter);}public void init(List<Integer> milliliter) {if (null == milliliter || milliliter.size() == 0)return;this.milliliter = delZero(milliliter);Resources res = getResources();tb = res.getDimension(R.dimen.historyscore_tb);interval_left_right = tb * 5.0f;interval_left = tb * 0.5f;margin_bottom=8*tb * 0.2f;paint_date = new Paint();paint_date.setStrokeWidth(tb * 0.1f);paint_date.setTextSize(tb * 1.2f);paint_date.setColor(fineLineColor);paint_brokenLine = new Paint();paint_brokenLine.setStrokeWidth(tb * 0.1f);paint_brokenLine.setColor(blueLineColor);paint_brokenLine.setAntiAlias(true);paint_dottedline = new Paint();paint_dottedline.setStyle(Paint.Style.STROKE);paint_dottedline.setColor(fineLineColor);paint_brokenline_big = new Paint();paint_brokenline_big.setStrokeWidth(tb * 0.2f);paint_brokenline_big.setColor(fineLineColor);paint_brokenline_big.setAntiAlias(true);framPanint = new Paint();framPanint.setAntiAlias(true);framPanint.setStrokeWidth(2f);path = new Path();bitmap_point = BitmapFactory.decodeResource(getResources(),R.drawable.icon_point_blue);setLayoutParams(new LayoutParams((int) (this.milliliter.size() * interval_left_right),LayoutParams.MATCH_PARENT));}/** * 移除左右為零的資料 * * @return */public List<Integer> delZero(List<Integer> milliliter) {List<Integer> list = new ArrayList<Integer>();int sta = 0;int end = 0;for (int i = 0; i < milliliter.size(); i++) {if (milliliter.get(i) != 0) {sta = i;break;}}for (int i = milliliter.size() - 1; i >= 0; i--) {if (milliliter.get(i) != 0) {end = i;break;}}for (int i = 0; i < milliliter.size(); i++) {if (i >= sta && i <= end) {list.add(milliliter.get(i));}}time_index = sta;//dotted_text = ((Collections.max(milliliter) - Collections .min(milliliter)) / 12.0f * 5.0f);return list;}protected void onDraw(Canvas c) {if (null == milliliter || milliliter.size() == 0)return;drawStraightLine(c);drawBrokenLine(c);drawDate(c);}/** * 繪製豎線 * * @param c */public void drawStraightLine(Canvas c) {int count_line = 0;for (int i = 0; i < milliliter.size(); i++) {if (i==0) {//繪製Y軸c.drawLine(interval_left_right * i, 0, interval_left_right * i, getHeight() - margin_bottom, paint_date);for (int j = 0; j <10; j++) {c.drawText(String.valueOf(10*(j+1)), 0 ,(getHeight()-margin_bottom)/10*(10-(j+1)), paint_date);if (j==5){//繪製虛線paint_dottedline.setColor(orangeLineColor);Path path = new Path();path.moveTo(0, (getHeight()-margin_bottom)/10*(10-(j+1)));path.lineTo(getWidth(), (getHeight()-margin_bottom)/10*(10-(j+1)));PathEffect effects = new DashPathEffect(new float[] { tb * 0.3f,tb * 0.3f, tb * 0.3f, tb * 0.3f }, tb * 0.1f);paint_dottedline.setPathEffect(effects);c.drawPath(path, paint_dottedline);} }continue;}//繪製豎線 連續四條為一組paint_dottedline.setColor(fineLineColor);if (count_line == 0) {c.drawLine(interval_left_right * i, 0, interval_left_right * i, getHeight() - margin_bottom, paint_date);}if (count_line == 2) {c.drawLine(interval_left_right * i, tb * 1.5f, interval_left_right * i, getHeight() - margin_bottom, paint_date);}if (count_line == 1 || count_line == 3) {Path path = new Path();path.moveTo(interval_left_right * i, tb * 1.5f);path.lineTo(interval_left_right * i, getHeight() - margin_bottom);PathEffect effects = new DashPathEffect(new float[] { tb * 0.3f, tb * 0.3f, tb * 0.3f, tb * 0.3f }, tb * 0.1f);paint_dottedline.setPathEffect(effects);c.drawPath(path, paint_dottedline);}count_line++;if (count_line >= 4) {count_line = 0;}}//繪製X軸c.drawLine(0, getHeight() - margin_bottom, getWidth(), getHeight() - margin_bottom, paint_brokenline_big);}/** * 繪製折線 * * @param c */public void drawBrokenLine(Canvas c) {int index = 0;float temp_x = 0;float temp_y = 0;//float base = (getHeight() - tb * 3.0f) / (Collections.max(milliliter) - Collections.min(milliliter));float base = (getHeight() - margin_bottom) / 100;Shader mShader = new LinearGradient(0, 0, 0, getHeight(), new int[] {Color.argb(100, 0, 255, 255), Color.argb(45, 0, 255, 255),Color.argb(10, 0, 255, 255) }, null, Shader.TileMode.CLAMP);framPanint.setShader(mShader);for (int i = 0; i < milliliter.size() - 1; i++) {Log.e("i", ""+milliliter.get(i));float x1 = interval_left_right * i;float y1 = getHeight() - margin_bottom - (base * milliliter.get(i));float Y1 = milliliter.get(i);float x2 = interval_left_right * (i + 1);float y2 = getHeight() - margin_bottom - (base * milliliter.get(i + 1));float Y2 = milliliter.get(i+1);if ((int) (base * milliliter.get(i + 1)) == 0 && index == 0) {index++;temp_x = x1;temp_y = y1;}if ((int) (base * milliliter.get(i + 1)) != 0 && index != 0) {index = 0;x1 = temp_x;y1 = temp_y;}paint_date.setColor(orangeLineColor);if (i==0) c.drawText(String.valueOf(Y1), x1, y1, paint_date);//繪出第一個值的大小if (index == 0) {c.drawText(String.valueOf(Y2), x2, y2, paint_date);//繪出第i+1個值的大小c.drawLine(x1, y1, x2, y2, paint_brokenLine);path.lineTo(x1, y1);if (i != 0)c.drawBitmap(bitmap_point,x1 - bitmap_point.getWidth() / 2,y1 - bitmap_point.getHeight() / 2, null);if (i == milliliter.size() - 2) {path.lineTo(x2, y2);path.lineTo(x2, getHeight());path.lineTo(0, getHeight());path.close();c.drawPath(path, framPanint);c.drawBitmap(bitmap_point,x2 - bitmap_point.getWidth() / 2,y2 - bitmap_point.getHeight() / 2, null);}}}paint_date.setColor(fineLineColor);}/** * 繪製時間 * * @param c */public void drawDate(Canvas c) {Date date=new Date();//取時間 Calendar calendar =new GregorianCalendar(); calendar.setTime(date); SimpleDateFormat dateFormat=new SimpleDateFormat("MM-dd");String[] dates=new String[milliliter.size()];for (int i = 0; i < milliliter.size(); i++) { calendar.add(calendar.DATE,1);//把日期往後增加一天.整數往後推,負數往前移動 date=calendar.getTime(); //這個時間就是日期往後推一天的結果 dates[i]=dateFormat.format(date).toString();}for (int i = 0; i < milliliter.size(); i += 1) {paint_date.setStrokeWidth(tb * 2.8f);c.drawText(dates[i], interval_left_right * i ,getHeight(), paint_date);}}}
Activity:
import java.util.ArrayList;import java.util.List;import android.app.Activity;import android.os.Bundle;import android.util.Log;import android.widget.RelativeLayout;import com.qianhua.healthy_brain.R;import com.qianhua.healthy_brain.widget.BrokenLine;public class TrainResultActivity extends Activity {RelativeLayout linear;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.train_result);List<Integer> lists = new ArrayList<Integer>();//線性圖 範圍0-100for (int i = 0; i < 48; i++) {if (i < 8 || i == 28 || i == 12 || i == 18 || i == 20 || i == 30|| i == 34) {lists.add(0);} else {//int item=getRandom(0, 100);//Log.w(""+i, ""+item);lists.add(getRandom(0, 100));}}linear= (RelativeLayout) findViewById(R.id.linear);linear.addView(new BrokenLine(this,lists));}public int getRandom(int min,int max){return (int) Math.round(Math.random()*(max-min)+min);}}
xml:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#f4f4f7" android:orientation="vertical" > <HorizontalScrollView android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_margin="10dp" android:scrollbars="none" > <RelativeLayout android:id="@+id/linear" android:layout_marginTop="30dp" android:layout_width="fill_parent" android:layout_height="fill_parent" > </RelativeLayout> </HorizontalScrollView> </LinearLayout></LinearLayout>
參考:http://www.apkbus.com/forum.php?mod=viewthread&tid=158365&extra=page%3D1
android自訂折線圖