網(wǎng)站首頁 編程語言 正文
本文實(shí)例為大家分享了Android開發(fā)RecyclerView實(shí)現(xiàn)折線圖效果的具體代碼,供大家參考,具體內(nèi)容如下
效果圖如下:
實(shí)現(xiàn)的關(guān)鍵是自定義的控件:
package com.example.recyclelinechart.test;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
public class LineView extends View {
? ? private int maxValue;//最大值
? ? private int minValue;//最小值
? ? private int currentValue;//當(dāng)前值
? ? private int lastValue;//上一個(gè)值
? ? private int nextValue;//下一個(gè)值
? ? private Paint mPaint;
? ? private int viewHeight;//控件高度
? ? private int viewWidth;//控件寬度
? ? private int distance;//文字高度
? ? private int pointX;//所有點(diǎn)的x坐標(biāo)
? ? private int pointY;//當(dāng)前點(diǎn)的Y
? ? private boolean drawLeftLine = true;//是否畫左邊的線
? ? private boolean drawRightLine = true;//是否畫右邊的線
? ? private float scale;//每一份占多少像素
? ? public LineView(Context context) {
? ? ? ? super(context);
? ? ? ? init();
? ? }
? ? public LineView(Context context, @Nullable AttributeSet attrs) {
? ? ? ? super(context, attrs);
? ? ? ? init();
? ? }
? ? public LineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
? ? ? ? super(context, attrs, defStyleAttr);
? ? ? ? init();
? ? }
? ? public void setCurrentValue(int currentValue) {
? ? ? ? this.currentValue = currentValue;
? ? ? ? invalidate();
? ? }
? ? public void setMaxValue(int maxValue) {
? ? ? ? this.maxValue = maxValue;
? ? }
? ? public void setMinValue(int minValue) {
? ? ? ? this.minValue = minValue;
? ? }
? ? private void init() {
? ? ? ? mPaint = new Paint();
? ? ? ? mPaint.setAntiAlias(true);
? ? ? ? mPaint.setStyle(Paint.Style.FILL);
? ? }
? ? @Override
? ? protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
? ? ? ? super.onMeasure(widthMeasureSpec, heightMeasureSpec);
? ? ? ? initValues();
? ? }
? ? private void initValues() {
? ? ? ? //計(jì)算文字高度
? ? ? ? mPaint.setTextSize(40);
? ? ? ? Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
? ? ? ? distance = (int) (fontMetrics.descent + Math.abs(fontMetrics.ascent));
? ? ? ? viewHeight = getMeasuredHeight();
? ? ? ? viewWidth = getMeasuredWidth();
? ? ? ? //lineView的x軸的中心
? ? ? ? pointX = viewWidth / 2;
? ? ? ? //(viewHeight - 2 * distance ?上下各留出文字的高度,防止顯示不全
? ? ? ? scale = (viewHeight - 2 * distance) / (maxValue - minValue);
? ? }
? ? @Override
? ? public void draw(Canvas canvas) {
? ? ? ? super.draw(canvas);
? ? ? ? pointY = (int) (scale * (maxValue - currentValue) + distance);
? ? ? ? drawGraph(canvas);
? ? ? ? drawPoint(canvas);
? ? ? ? drawValue(canvas);
? ? }
? ? /**
? ? ?* 畫數(shù)字
? ? ?*
? ? ?* @param canvas
? ? ?*/
? ? private void drawValue(Canvas canvas) {
? ? ? ? mPaint.setTextSize(40);
? ? ? ? mPaint.setColor(Color.parseColor("#ff333333"));
? ? ? ? mPaint.setTextAlign(Paint.Align.CENTER);
? ? ? ? Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
? ? ? ? //取字體高度的三分之一
? ? ? ? canvas.drawText(currentValue + "", viewWidth / 2, pointY - (fontMetrics.descent + Math.abs(fontMetrics.ascent)) / 3, mPaint);
? ? }
? ? public void setlastValue(int lastValue) {
? ? ? ? this.lastValue = lastValue;
? ? }
? ? public void setNextValue(int nextValue) {
? ? ? ? this.nextValue = nextValue;
? ? }
? ? /**
? ? ?* 畫折線
? ? ?*
? ? ?* @param canvas
? ? ?*/
? ? private void drawGraph(Canvas canvas) {
? ? ? ? mPaint.setColor(Color.BLUE);
? ? ? ? mPaint.setStrokeWidth(8);
? ? ? ? if (drawLeftLine) {
? ? ? ? ? ? float middleValue = (currentValue + lastValue) / 2f;
? ? ? ? ? ? float middleY = (scale * (maxValue - middleValue) + distance);
? ? ? ? ? ? //ax+b = y ? 二元一次方程,向左多畫一點(diǎn)計(jì)算y值
? ? ? ? ? ? float a = (middleY - pointY) * 1f / (0 - pointX);
? ? ? ? ? ? float b = (0 * pointY - pointX * middleY) * 1f / (0 - pointX);
? ? ? ? ? ? middleY = a * (0 - 10) + b;
? ? ? ? ? ? canvas.drawLine(0 - 10, middleY, pointX, pointY, mPaint);
? ? ? ? }
? ? ? ? if (drawRightLine) {
? ? ? ? ? ? float middleValue = (currentValue + nextValue) / 2f;
? ? ? ? ? ? float middleY = scale * (maxValue - middleValue) + distance;
? ? ? ? ? ? //向右多畫一點(diǎn),機(jī)制同上
? ? ? ? ? ? float a = (middleY - pointY) * 1f / (viewWidth - pointX);
? ? ? ? ? ? float b = (pointX * middleY - viewWidth * pointY) * 1f / (pointX - viewWidth);
? ? ? ? ? ? middleY = a * (viewWidth + 10) + b;
? ? ? ? ? ? canvas.drawLine(pointX, pointY, viewWidth + 10, middleY, mPaint);
? ? ? ? }
? ? }
? ? /**
? ? ?* 畫數(shù)字下面的小圓圈
? ? ?*
? ? ?* @param canvas
? ? ?*/
? ? private void drawPoint(Canvas canvas) {
? ? ? ? mPaint.setColor(Color.RED);
? ? ? ? mPaint.setPathEffect(null);
? ? ? ? mPaint.setStrokeWidth(10);
? ? ? ? mPaint.setStyle(Paint.Style.FILL);
? ? ? ? canvas.drawCircle(pointX, pointY, 10, mPaint);
? ? }
? ? public void setDrawLeftLine(boolean drawLeftLine) {
? ? ? ? this.drawLeftLine = drawLeftLine;
? ? }
? ? public void setDrawRightLine(boolean drawRightLine) {
? ? ? ? this.drawRightLine = drawRightLine;
? ? }
}
適配器
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
? ? private int minValue;
? ? private int maxValue;
? ? private List<Integer> data;
? ? public MyAdapter(int minValue, int maxValue, List<Integer> data) {
? ? ? ? this.minValue = minValue;
? ? ? ? this.maxValue = maxValue;
? ? ? ? this.data = data;
? ? }
? ? @Override
? ? public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
? ? ? ? View layout = LayoutInflater.from(parent.getContext()).inflate(R.layout.test_line, parent, false);
? ? ? ? return new ViewHolder(layout);
? ? }
? ? @Override
? ? public void onBindViewHolder(ViewHolder holder, int position) {
? ? ? ? if (position == 0) {
? ? ? ? ? ? holder.lineView.setDrawLeftLine(false);
? ? ? ? } else {
? ? ? ? ? ? holder.lineView.setDrawLeftLine(true);
? ? ? ? ? ? holder.lineView.setlastValue((data.get(position - 1)));
? ? ? ? }
? ? ? ? holder.lineView.setMaxValue(maxValue);
? ? ? ? holder.lineView.setMinValue(minValue);
? ? ? ? holder.lineView.setCurrentValue((data.get(position)));
? ? ? ? if (position == data.size() - 1) {
? ? ? ? ? ? holder.lineView.setDrawRightLine(false);
? ? ? ? } else {
? ? ? ? ? ? holder.lineView.setDrawRightLine(true);
? ? ? ? ? ? holder.lineView.setNextValue((data.get(position + 1)));
? ? ? ? }
? ? }
? ? @Override
? ? public int getItemCount() {
? ? ? ? return data.size();
? ? }
? ? class ViewHolder extends RecyclerView.ViewHolder {
? ? ? ? LineView lineView;
? ? ? ? public ViewHolder(View itemView) {
? ? ? ? ? ? super(itemView);
? ? ? ? ? ? this.lineView = itemView.findViewById(R.id.item);
? ? ? ? }
? ? }
}
item的布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ? ? android:layout_width="wrap_content" ? ? android:layout_height="wrap_content" ? ? android:orientation="vertical"> ? ? <TextView ? ? ? ? android:layout_width="wrap_content" ? ? ? ? android:layout_height="wrap_content" ? ? ? ? android:layout_gravity="center_horizontal" ? ? ? ? android:layout_marginTop="20dp" ? ? ? ? android:layout_marginBottom="5dp" ? ? ? ? android:text="文字" /> ? ? <com.example.recyclelinechart.test.LineView ? ? ? ? android:id="@+id/item" ? ? ? ? android:layout_width="100dp" ? ? ? ? android:layout_height="100dp" /> ? ? <ImageView ? ? ? ? android:layout_width="20dp" ? ? ? ? android:layout_height="20dp" ? ? ? ? android:layout_gravity="center_horizontal" ? ? ? ? android:layout_marginBottom="20dp" ? ? ? ? android:src="@mipmap/ic_launcher" /> </LinearLayout>
使用
MyAdapter myAdapter = new MyAdapter(2, 30, integers);
? ? ? ? recyclerView.setLayoutManager(new LinearLayoutManager(this, RecyclerView.HORIZONTAL, false));
? ? ? ? recyclerView.setAdapter(myAdapter);
原文鏈接:https://blog.csdn.net/u011609853/article/details/104508640
相關(guān)推薦
- 2022-12-12 React?中state與props更新深入解析_React
- 2021-11-10 Android?Studio設(shè)置繪制布局時(shí)的視圖_Android
- 2023-02-28 ts之 Mixin混入(ts對(duì)象的混入、類的混入)
- 2022-05-12 Kotlin 擴(kuò)展函數(shù) 之 可空
- 2022-11-03 C#事件中關(guān)于sender的用法解讀_C#教程
- 2023-01-28 架構(gòu)師說比起404我們更怕200錯(cuò)誤_相關(guān)技巧
- 2022-07-19 Compose中更靈活易用的TextField以及密碼輸入框
- 2022-07-11 go語言環(huán)境搭建
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支