Android 사용자 정의 기둥 모양 도표 방법 인 스 턴 스
본 고 는 예제 코드 를 통 해 간단 한 직 방 도 표를 어떻게 정의 하 는 지 소개 할 것 이다.이 도 표 는 매우 보 이 는 직 방 도표 가 아니 라 그룹 을 나 눌 수 있다.이 글 은 원리 와 지나치게 관련 되 지 않 고 비교적 간단 합 니 다.예시 그림 은 다음 과 같 습 니 다.
이 예제 의 코드 실현 에 있어 서 사실은 좌표 축,문자,직사 도 의 위치 통제 에 중심 을 두 고 미끄럼 거리 에 따라 동적 으로 업데이트 해 야 한다.주의사항 은 예시 코드 에 표 시 됩 니 다.다음은 예제 코드 를 붙 입 니 다.
public class MultiGroupHistogramView extends View {
private int width;
private int height;
//
private int coordinateAxisWidth;
//
private int groupNameTextSize;
//
private int groupInterval;
//
private int histogramInterval;
private int histogramValueTextSize;
//
private int histogramValueDecimalCount;
private int histogramHistogramWidth;
private int chartPaddingTop;
private int histogramPaddingStart;
private int histogramPaddingEnd;
// X
private int distanceFormGroupNameToAxis;
//
private int distanceFromValueToHistogram;
//
private int maxHistogramHeight;
//
private Paint coordinateAxisPaint;
//
private Paint groupNamePaint;
private Paint.FontMetrics groupNameFontMetrics;
private Paint.FontMetrics histogramValueFontMetrics;
//
private Paint histogramValuePaint;
//
private Paint histogramPaint;
//
private Rect histogramPaintRect;
//
private int histogramContentWidth;
// shader color, , 3 , SparseArray 3 shader color
private SparseArray<int[]> histogramShaderColorArray;
private List<MultiGroupHistogramGroupData> dataList;
private SparseArray<Float> childMaxValueArray;
private Scroller scroller;
private int minimumVelocity;
private int maximumVelocity;
private VelocityTracker velocityTracker;
public MultiGroupHistogramView(Context context) {
this(context, null);
}
public MultiGroupHistogramView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MultiGroupHistogramView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
private void init(AttributeSet attrs) {
setLayerType(View.LAYER_TYPE_HARDWARE, null);
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MultiGroupHistogramView);
coordinateAxisWidth = typedArray.getDimensionPixelSize(R.styleable.MultiGroupHistogramView_coordinateAxisWidth, DisplayUtil.dp2px(2));
//
int coordinateAxisColor = typedArray.getColor(R.styleable.MultiGroupHistogramView_coordinateAxisColor, Color.parseColor("#434343"));
//
int groupNameTextColor = typedArray.getColor(R.styleable.MultiGroupHistogramView_groupNameTextColor, Color.parseColor("#CC202332"));
groupNameTextSize = typedArray.getDimensionPixelSize(R.styleable.MultiGroupHistogramView_groupNameTextSize, DisplayUtil.dp2px(15));
groupInterval = typedArray.getDimensionPixelSize(R.styleable.MultiGroupHistogramView_groupInterval, DisplayUtil.dp2px(30));
histogramInterval = typedArray.getDimensionPixelSize(R.styleable.MultiGroupHistogramView_histogramInterval, DisplayUtil.dp2px(10));
//
int histogramValueTextColor = typedArray.getColor(R.styleable.MultiGroupHistogramView_histogramValueTextColor, Color.parseColor("#CC202332"));
histogramValueTextSize = typedArray.getDimensionPixelSize(R.styleable.MultiGroupHistogramView_histogramValueTextSize, DisplayUtil.dp2px(12));
histogramValueDecimalCount = typedArray.getInt(R.styleable.MultiGroupHistogramView_histogramValueDecimalCount, 0);
histogramHistogramWidth = typedArray.getDimensionPixelSize(R.styleable.MultiGroupHistogramView_histogramHistogramWidth, DisplayUtil.dp2px(20));
chartPaddingTop = typedArray.getDimensionPixelSize(R.styleable.MultiGroupHistogramView_chartPaddingTop, DisplayUtil.dp2px(10));
histogramPaddingStart = typedArray.getDimensionPixelSize(R.styleable.MultiGroupHistogramView_histogramPaddingStart, DisplayUtil.dp2px(15));
histogramPaddingEnd = typedArray.getDimensionPixelSize(R.styleable.MultiGroupHistogramView_histogramPaddingEnd, DisplayUtil.dp2px(15));
distanceFormGroupNameToAxis = typedArray.getDimensionPixelSize(R.styleable.MultiGroupHistogramView_distanceFormGroupNameToAxis, DisplayUtil.dp2px(15));
distanceFromValueToHistogram = typedArray.getDimensionPixelSize(R.styleable.MultiGroupHistogramView_distanceFromValueToHistogram, DisplayUtil.dp2px(10));
typedArray.recycle();
coordinateAxisPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
coordinateAxisPaint.setStyle(Paint.Style.FILL);
coordinateAxisPaint.setStrokeWidth(coordinateAxisWidth);
coordinateAxisPaint.setColor(coordinateAxisColor);
groupNamePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
groupNamePaint.setTextSize(groupNameTextSize);
groupNamePaint.setColor(groupNameTextColor);
groupNameFontMetrics = groupNamePaint.getFontMetrics();
histogramValuePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
histogramValuePaint.setTextSize(histogramValueTextSize);
histogramValuePaint.setColor(histogramValueTextColor);
histogramValueFontMetrics = histogramValuePaint.getFontMetrics();
histogramPaintRect = new Rect();
histogramPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
scroller = new Scroller(getContext(), new LinearInterpolator());
ViewConfiguration configuration = ViewConfiguration.get(getContext());
minimumVelocity = configuration.getScaledMinimumFlingVelocity();
maximumVelocity = configuration.getScaledMaximumFlingVelocity();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getMeasuredWidth();
height = getMeasuredHeight();
maxHistogramHeight = height - groupNameTextSize - coordinateAxisWidth - distanceFormGroupNameToAxis - distanceFromValueToHistogram - histogramValueTextSize - chartPaddingTop;
}
/**
*
* @param direction : ( ); : ( )
* ScaollView HorizontalScrollView
*/
@Override
public boolean canScrollHorizontally(int direction) {
if (direction > 0) {
return histogramContentWidth - getScrollX() - width + histogramPaddingStart + histogramPaddingEnd > 0;
} else {
return getScrollX() > 0;
}
}
/**
*
* @param direction : ( ); : ( )
* ScaollView HorizontalScrollView
*/
private int getMaxCanScrollX(int direction) {
if (direction > 0) {
return histogramContentWidth - getScrollX() - width + histogramPaddingStart + histogramPaddingEnd > 0 ?
histogramContentWidth - getScrollX() - width + histogramPaddingStart + histogramPaddingEnd : 0;
} else if (direction < 0) {
return getScrollX();
}
return 0;
}
private float lastX;
@Override
public boolean onTouchEvent(MotionEvent event) {
initVelocityTrackerIfNotExists();
velocityTracker.addMovement(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
if (!scroller.isFinished()) {
scroller.abortAnimation();
}
lastX = event.getX();
return true;
}
case MotionEvent.ACTION_MOVE: {
int deltaX = (int) (event.getX() - lastX);
lastX = event.getX();
//
if (deltaX > 0 && canScrollHorizontally(-1)) {
scrollBy(-Math.min(getMaxCanScrollX(-1), deltaX), 0);
} else if (deltaX < 0 && canScrollHorizontally(1)) {
scrollBy(Math.min(getMaxCanScrollX(1), -deltaX), 0);
}
break;
}
case MotionEvent.ACTION_UP: {
velocityTracker.computeCurrentVelocity(1000, maximumVelocity);
int velocityX = (int) velocityTracker.getXVelocity();
fling(velocityX);
recycleVelocityTracker();
break;
}
case MotionEvent.ACTION_CANCEL: {
recycleVelocityTracker();
break;
}
}
return super.onTouchEvent(event);
}
private void initVelocityTrackerIfNotExists() {
if (velocityTracker == null) {
velocityTracker = VelocityTracker.obtain();
}
}
private void recycleVelocityTracker() {
if (velocityTracker != null) {
velocityTracker.recycle();
velocityTracker = null;
}
}
// ACTION_UP
private void fling(int velocityX) {
if (Math.abs(velocityX) > minimumVelocity) {
if (Math.abs(velocityX) > maximumVelocity) {
velocityX = maximumVelocity * velocityX / Math.abs(velocityX);
}
scroller.fling(getScrollX(), getScrollY(), -velocityX, 0, 0, histogramContentWidth + histogramPaddingStart - width, 0, 0);
}
}
@Override
public void computeScroll() {
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), 0);
}
}
public void setDataList(@NonNull List<MultiGroupHistogramGroupData> dataList) {
this.dataList = dataList;
if (childMaxValueArray == null) {
childMaxValueArray = new SparseArray<>();
} else {
childMaxValueArray.clear();
}
histogramContentWidth = 0;
for (MultiGroupHistogramGroupData groupData : dataList) {
List<MultiGroupHistogramChildData> childDataList = groupData.getChildDataList();
if (childDataList != null && childDataList.size() > 0) {
for (int i = 0; i < childDataList.size(); i++) {
histogramContentWidth += histogramHistogramWidth + histogramInterval;
MultiGroupHistogramChildData childData = childDataList.get(i);
Float childMaxValue = childMaxValueArray.get(i);
if (childMaxValue == null || childMaxValue < childData.getValue()) {
childMaxValueArray.put(i, childData.getValue());
}
}
histogramContentWidth += groupInterval - histogramInterval;
}
}
histogramContentWidth += -groupInterval;
}
/**
* ( , )
*/
public void setHistogramColor(int[]... colors) {
if (colors != null && colors.length > 0) {
if (histogramShaderColorArray == null) {
histogramShaderColorArray = new SparseArray<>();
} else {
histogramShaderColorArray.clear();
}
for (int i = 0; i < colors.length; i++) {
histogramShaderColorArray.put(i, colors[i]);
}
}
}
@Override
protected void onDraw(Canvas canvas) {
if (width == 0 || height == 0) {
return;
}
int scrollX = getScrollX();
int axisBottom = height - groupNameTextSize - distanceFormGroupNameToAxis - coordinateAxisWidth / 2;
canvas.drawLine(coordinateAxisWidth / 2 + scrollX, 0, coordinateAxisWidth / 2 + scrollX, axisBottom, coordinateAxisPaint);
canvas.drawLine(scrollX, axisBottom, width + scrollX, axisBottom, coordinateAxisPaint);
if (dataList != null && dataList.size() > 0) {
int xAxisOffset = histogramPaddingStart; // x
for (MultiGroupHistogramGroupData groupData : dataList) {
List<MultiGroupHistogramChildData> childDataList = groupData.getChildDataList();
if (childDataList != null && childDataList.size() > 0) {
int groupWidth = 0;
for (int i = 0; i < childDataList.size(); i++) {
MultiGroupHistogramChildData childData = childDataList.get(i);
histogramPaintRect.left = xAxisOffset;
histogramPaintRect.right = histogramPaintRect.left + histogramHistogramWidth;
int childHistogramHeight;
if (childData.getValue() <= 0 || childMaxValueArray.get(i) <= 0) {
childHistogramHeight = 0;
} else {
childHistogramHeight = (int) (childData.getValue() / childMaxValueArray.get(i) * maxHistogramHeight);
}
histogramPaintRect.top = height - childHistogramHeight - coordinateAxisWidth - distanceFormGroupNameToAxis - groupNameTextSize;
histogramPaintRect.bottom = histogramPaintRect.top + childHistogramHeight;
int[] histogramShaderColor = histogramShaderColorArray.get(i);
LinearGradient shader = null;
if (histogramShaderColor != null && histogramShaderColor.length > 0) {
shader = getHistogramShader(histogramPaintRect.left, chartPaddingTop + distanceFromValueToHistogram + histogramValueTextSize,
histogramPaintRect.right, histogramPaintRect.bottom, histogramShaderColor);
}
histogramPaint.setShader(shader);
canvas.drawRect(histogramPaintRect, histogramPaint);
String childHistogramHeightValue = StringUtil.NumericScaleByFloor(String.valueOf(childData.getValue()), histogramValueDecimalCount) + childData.getSuffix();
float valueTextX = xAxisOffset + (histogramHistogramWidth - histogramValuePaint.measureText(childHistogramHeightValue)) / 2;
// Y
float valueTextY = histogramPaintRect.top - distanceFormGroupNameToAxis + (histogramValueFontMetrics.bottom) / 2;
canvas.drawText(childHistogramHeightValue, valueTextX, valueTextY, histogramValuePaint);
int deltaX = i < childDataList.size() - 1 ? histogramHistogramWidth + histogramInterval : histogramHistogramWidth;
groupWidth += deltaX;
//
xAxisOffset += i == childDataList.size() - 1 ? deltaX + groupInterval : deltaX;
}
String groupName = groupData.getGroupName();
float groupNameTextWidth = groupNamePaint.measureText(groupName);
float groupNameTextX = xAxisOffset - groupWidth - groupInterval + (groupWidth - groupNameTextWidth) / 2;
// Y
float groupNameTextY = (height - groupNameFontMetrics.bottom / 2);
canvas.drawText(groupName, groupNameTextX, groupNameTextY, groupNamePaint);
}
}
}
}
private LinearGradient getHistogramShader(float x0, float y0, float x1, float y1, int[] colors) {
return new LinearGradient(x0, y0, x1, y1, colors, null, Shader.TileMode.CLAMP);
}
}
코드 는 이 점 에서 읽 기 어렵 지 않 을 것 입 니 다.궁금 한 점 이 있 으 면 메 시 지 를 환영 합 니 다.사용자 정의 속성 은 다음 과 같 습 니 다.
<declare-styleable name="MultiGroupHistogramView">
<attr name="coordinateAxisWidth" format="dimension" />
<attr name="coordinateAxisColor" format="color" />
<attr name="groupNameTextColor" format="color" />
<attr name="groupNameTextSize" format="dimension" />
<attr name="groupInterval" format="dimension" />
<attr name="histogramInterval" format="dimension" />
<attr name="histogramValueTextColor" format="color" />
<attr name="histogramValueTextSize" format="dimension" />
<attr name="histogramHistogramWidth" format="dimension" />
<attr name="histogramPaddingStart" format="dimension" />
<attr name="histogramPaddingEnd" format="dimension" />
<attr name="chartPaddingTop" format="dimension" />
<attr name="distanceFormGroupNameToAxis" format="dimension" />
<attr name="distanceFromValueToHistogram" format="dimension" />
<!-- -->
<attr name="histogramValueDecimalCount">
<enum name="ZERO" value="0" />
<enum name="ONE" value="1" />
<enum name="TWO" value="2" />
</attr>
</declare-styleable>
아래 에 사용 방법 을 붙 입 니 다:
private void initMultiGroupHistogramView() {
Random random = new Random();
int groupSize = random.nextInt(5) + 10;
List<MultiGroupHistogramGroupData> groupDataList = new ArrayList<>();
//
for (int i = 0; i < groupSize; i++) {
List<MultiGroupHistogramChildData> childDataList = new ArrayList<>();
MultiGroupHistogramGroupData groupData = new MultiGroupHistogramGroupData();
groupData.setGroupName(" " + (i + 1) + " ");
MultiGroupHistogramChildData childData1 = new MultiGroupHistogramChildData();
childData1.setSuffix(" ");
childData1.setValue(random.nextInt(50) + 51);
childDataList.add(childData1);
MultiGroupHistogramChildData childData2 = new MultiGroupHistogramChildData();
childData2.setSuffix("%");
childData2.setValue(random.nextInt(50) + 51);
childDataList.add(childData2);
groupData.setChildDataList(childDataList);
groupDataList.add(groupData);
}
multiGroupHistogramView.setDataList(groupDataList);
int[] color1 = new int[]{getResources().getColor(R.color.color_orange), getResources().getColor(R.color.colorPrimary)};
int[] color2 = new int[]{getResources().getColor(R.color.color_supper_tip_normal), getResources().getColor(R.color.bg_supper_selected)};
//
multiGroupHistogramView.setHistogramColor(color1, color2);
}
전체 예시:https://github.com/670832188/TestApp ( 로 컬 다운로드 )총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.