Android 프로 그래 밍 은 canvas 가 기둥 모양 의 통계 도 를 그 리 는 기능 을 실현 합 니 다[너비 와 분 도 를 자동 으로 계산 하고 좌우 로 미 끄 러 질 수 있 습 니 다]
여기 서 간단 한 기둥 모양 통계 도 를 실현 했다.다음 과 같다.
특징:
1.데이터 소스 에 따라 각 항목 의 높이,너비,간격 을 자동 으로 계산 하고 분 도 를 자동 으로 계산한다.
2.항목 수가 많 을 때 좌우 로 미 끄 러 지 며 모든 내용 을 볼 수 있 고 도형,문자 가 동시에 미 끄 러 지 며 손 을 놓 으 면 점점 멈춘다(바로 멈 추 는 것 이 아니 라).
코드:
(1)핵심 코드:BarChartView.Java
package com.sina.appbarchart;
import android.app.Activity;
import android.content.Context;
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.Rect;
import android.support.annotation.NonNull;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* :
* Created by hanj on 14-12-30.
*/
public class BarChartView extends View {
private int screenW, screenH;
private BarChartItemBean[] mItems;
//max value in mItems.
private float maxValue;
//max height of the bar
private int maxHeight;
private int[] mBarColors = new int[]{Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.MAGENTA, Color.CYAN};
private Paint barPaint, linePaint, textPaint;
private Rect barRect, leftWhiteRect, rightWhiteRect;
private Path textPath;
private int leftMargin, topMargin, smallMargin;
//the width of one bar item
private int barItemWidth;
//the spacing between two bar items.
private int barSpace;
//the width of the line.
private int lineStrokeWidth;
/**
* The x-position of y-index and the y-position of the x-index..
*/
private float x_index_startY, y_index_startX;
private Bitmap arrowBmp;
private Rect x_index_arrowRect, y_index_arrowRect;
private static final int BG_COLOR = Color.parseColor("#E5E5E5");
public BarChartView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
screenW = ScreenUtils.getScreenW(context);
screenH = ScreenUtils.getScreenH(context);
leftMargin = ScreenUtils.dp2px(context, 16);
topMargin = ScreenUtils.dp2px(context, 40);
smallMargin = ScreenUtils.dp2px(context, 6);
barPaint = new Paint();
barPaint.setColor(mBarColors[0]);
linePaint = new Paint();
lineStrokeWidth = ScreenUtils.dp2px(context, 1);
linePaint.setStrokeWidth(lineStrokeWidth);
textPaint = new Paint();
textPaint.setAntiAlias(true);
barRect = new Rect(0, 0, 0, 0);
textPath = new Path();
leftWhiteRect = new Rect(0, 0, 0, screenH);
rightWhiteRect = new Rect(screenW - leftMargin, 0, screenW, screenH);
arrowBmp = BitmapFactory.decodeResource(context.getResources(), R.drawable.arrow_up);
}
//
private boolean statusHeightHasGet;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!statusHeightHasGet) {
subStatusBarHeight();
statusHeightHasGet = true;
}
//draw background
canvas.drawColor(BG_COLOR);
//bounds
checkLeftMoving();
textPaint.setTextSize(ScreenUtils.dp2px(getContext(), 16));
for (int i = 0; i < mItems.length; i++) {
//draw bar rect
barRect.left = (int) y_index_startX + barItemWidth * i + barSpace * (i + 1) - (int) leftMoving;
barRect.top = topMargin * 2 + (int) (maxHeight * (1.0f - mItems[i].itemValue / maxValue));
barRect.right = barRect.left + barItemWidth;
barPaint.setColor(mBarColors[i % mBarColors.length]);
canvas.drawRect(barRect, barPaint);
//draw type text
String typeText = mItems[i].itemType;
float textPathStartX = barRect.left + barItemWidth / 2 -
(float) (Math.sin(Math.PI / 6)) * textPaint.measureText(" ") / 2;
float textPathStartY = barRect.bottom;
textPath.reset();
textPath.moveTo(textPathStartX, textPathStartY);
textPath.lineTo(textPathStartX + (float) (1000 * Math.tan(Math.PI / 6)), textPathStartY + 1000);
canvas.drawTextOnPath(typeText, textPath, smallMargin * 1.5f, smallMargin * 2, textPaint);
//draw value text
String valueText = String.valueOf(mItems[i].itemValue);
canvas.drawText(valueText, barRect.left - (textPaint.measureText(valueText) - barItemWidth) / 2,
barRect.top - smallMargin, textPaint);
}
//draw left white space and right white space
int c = barPaint.getColor();
barPaint.setColor(BG_COLOR);
leftWhiteRect.right = (int) y_index_startX;
canvas.drawRect(leftWhiteRect, barPaint);
canvas.drawRect(rightWhiteRect, barPaint);
barPaint.setColor(c);
//draw x-index line.
canvas.drawLine(
y_index_startX - lineStrokeWidth / 2,
x_index_startY,
screenW - leftMargin,
x_index_startY,
linePaint);
//draw y-index line.
canvas.drawLine(
y_index_startX,
x_index_startY + lineStrokeWidth / 2,
y_index_startX,
topMargin / 2,
linePaint);
canvas.drawBitmap(arrowBmp, null, y_index_arrowRect, null);
canvas.save();
canvas.rotate(90, (x_index_arrowRect.left + x_index_arrowRect.right) / 2, (x_index_arrowRect.top + x_index_arrowRect.bottom) / 2);
canvas.drawBitmap(arrowBmp, null, x_index_arrowRect, null);
canvas.restore();
//draw division value
int maxDivisionValueHeight = (int) (maxHeight * 1.0f / maxValue * maxDivisionValue);
textPaint.setTextSize(ScreenUtils.dp2px(getContext(), 10));
for (int i = 1; i <= 10; i++) {
float startY = barRect.bottom - maxDivisionValueHeight * 0.1f * i;
if (startY < topMargin / 2) {
break;
}
canvas.drawLine(y_index_startX, startY, y_index_startX + 10, startY, linePaint);
String text = String.valueOf(maxDivisionValue * 0.1f * i);
canvas.drawText(text,
y_index_startX - textPaint.measureText(text) - 5,
startY + textPaint.measureText("0") / 2,
textPaint);
}
}
private float leftMoving;
private float lastPointX;
private float movingLeftThisTime = 0.0f;
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
int type = event.getAction();
switch (type) {
case MotionEvent.ACTION_DOWN:
lastPointX = event.getRawX();
break;
case MotionEvent.ACTION_MOVE:
float x = event.getRawX();
movingLeftThisTime = lastPointX - x;
leftMoving += movingLeftThisTime;
lastPointX = x;
invalidate();
break;
case MotionEvent.ACTION_UP:
//smooth scroll
new Thread(new SmoothScrollThread(movingLeftThisTime)).start();
break;
default:
return super.onTouchEvent(event);
}
return true;
}
/**
* Check the value of leftMoving to ensure that the view is not out of the screen.
*/
private void checkLeftMoving() {
if (leftMoving < 0) {
leftMoving = 0;
}
if (leftMoving > (maxRight - minRight)) {
leftMoving = maxRight - minRight;
}
}
public BarChartItemBean[] getItems() {
return mItems;
}
public void setItems(BarChartItemBean[] items) {
if (items == null) {
throw new RuntimeException("BarChartView.setItems(): the param items cannot be null.");
}
if (items.length == 0) {
return;
}
this.mItems = items;
//Calculate the max value.
maxValue = items[0].itemValue;
for (BarChartItemBean bean : items) {
if (bean.itemValue > maxValue) {
maxValue = bean.itemValue;
}
}
//Calculate the max division value.
getRange(maxValue, 0);
//Get the width of each bar.
getBarItemWidth(screenW, items.length);
//Refresh the view.
invalidate();
}
private int maxRight, minRight;
/**
* Get the width of each bar which is depended on the screenW and item count.
*/
private void getBarItemWidth(int screenW, int itemCount) {
//The min width of the bar is 50dp.
int minBarWidth = ScreenUtils.dp2px(getContext(), 40);
//The min width of spacing.
int minBarSpacing = ScreenUtils.dp2px(getContext(), 30);
barItemWidth = (screenW - leftMargin * 2) / (itemCount + 3);
barSpace = (screenW - leftMargin * 2 - barItemWidth * itemCount) / (itemCount + 1);
if (barItemWidth < minBarWidth || barSpace < minBarSpacing) {
barItemWidth = minBarWidth;
barSpace = minBarSpacing;
}
maxRight = (int) y_index_startX + lineStrokeWidth + (barSpace + barItemWidth) * mItems.length;
minRight = screenW - leftMargin - barSpace;
}
/**
* Sub the height of status bar and action bar to get the accurate height of screen.
*/
private void subStatusBarHeight() {
//The height of the status bar
int statusHeight = ScreenUtils.getStatusBarHeight((Activity) getContext());
//The height of the actionBar
ActionBar ab = ((ActionBarActivity) getContext()).getSupportActionBar();
int abHeight = ab == null ? 0 : ab.getHeight();
screenH -= (statusHeight + abHeight);
barRect.top = topMargin * 2;
barRect.bottom = screenH - topMargin * 3;
maxHeight = barRect.bottom - barRect.top;
x_index_startY = barRect.bottom;
x_index_arrowRect = new Rect(screenW - leftMargin, (int) (x_index_startY - 10),
screenW - leftMargin + 10, (int) (x_index_startY + 10));
}
//The max and min division value.
private float maxDivisionValue, minDivisionValue;
//Get the max and min division value by the max and min value in mItems.
private void getRange(float maxValue, float minValue) {
//max
int scale = Utility.getScale(maxValue);
float unscaledValue = (float) (maxValue / Math.pow(10, scale));
maxDivisionValue = (float) (getRangeTop(unscaledValue) * Math.pow(10, scale));
y_index_startX = getDivisionTextMaxWidth(maxDivisionValue) + 10;
y_index_arrowRect = new Rect((int) (y_index_startX - 5), topMargin / 2 - 20,
(int) (y_index_startX + 5), topMargin / 2);
}
private float getRangeTop(float value) {
//value: [1,10)
if (value < 1.2) {
return 1.2f;
}
if (value < 1.5) {
return 1.5f;
}
if (value < 2.0) {
return 2.0f;
}
if (value < 3.0) {
return 3.0f;
}
if (value < 4.0) {
return 4.0f;
}
if (value < 5.0) {
return 5.0f;
}
if (value < 6.0) {
return 6.0f;
}
if (value < 8.0) {
return 8.0f;
}
return 10.0f;
}
/**
* Get the max width of the division value text.
*/
private float getDivisionTextMaxWidth(float maxDivisionValue) {
Paint textPaint = new Paint();
textPaint.setTextSize(ScreenUtils.dp2px(getContext(), 10));
float max = textPaint.measureText(String.valueOf(maxDivisionValue * 0.1f));
for (int i = 2; i <= 10; i++) {
float w = textPaint.measureText(String.valueOf(maxDivisionValue * 0.1f * i));
if (w > max) {
max = w;
}
}
return max;
}
/**
* Use this thread to create a smooth scroll after ACTION_UP.
*/
private class SmoothScrollThread implements Runnable {
float lastMoving;
boolean scrolling = true;
private SmoothScrollThread(float lastMoving) {
this.lastMoving = lastMoving;
scrolling = true;
}
@Override
public void run() {
while (scrolling) {
long start = System.currentTimeMillis();
lastMoving = (int) (0.9f * lastMoving);
leftMoving += lastMoving;
checkLeftMoving();
postInvalidate();
if (Math.abs(lastMoving) < 5) {
scrolling = false;
}
long end = System.currentTimeMillis();
if (end - start < 20) {
try {
Thread.sleep(20 - (end - start));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
/**
* A model class to keep the bar item info.
*/
static class BarChartItemBean {
private String itemType;
private float itemValue;
public BarChartItemBean(String itemType, float itemValue) {
this.itemType = itemType;
this.itemValue = itemValue;
}
}
}
(2)이 사용자 정의 구성 요소 의 사용:
package com.sina.appbarchart;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BarChartView barChartView = (BarChartView) findViewById(R.id.bar_chart);
BarChartView.BarChartItemBean[] items = new BarChartView.BarChartItemBean[]{
new BarChartView.BarChartItemBean(" ", 300),
new BarChartView.BarChartItemBean(" ", 200),
new BarChartView.BarChartItemBean(" ", 270),
new BarChartView.BarChartItemBean(" ", 110),
new BarChartView.BarChartItemBean(" ", 120),
new BarChartView.BarChartItemBean(" ", 80),
new BarChartView.BarChartItemBean(" ", 110),
new BarChartView.BarChartItemBean(" ", 280)
};
barChartView.setItems(items);
}
}
전체 인 스 턴 스 코드 는 여 기 를 클릭 하 십시오본 사이트 다운로드더 많은 안 드 로 이 드 관련 내용 에 관심 이 있 는 독자 들 은 본 사이트 의 주 제 를 볼 수 있다.,,,,,,,
본 고 에서 말 한 것 이 여러분 의 안 드 로 이 드 프로 그래 밍 에 도움 이 되 기 를 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.