Android開發(fā)RecyclerView實現(xiàn)折線圖效果
本文實例為大家分享了Android開發(fā)RecyclerView實現(xiàn)折線圖效果的具體代碼,供大家參考,具體內(nèi)容如下
效果圖如下:

實現(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;//上一個值
? ? private int nextValue;//下一個值
? ? private Paint mPaint;
? ? private int viewHeight;//控件高度
? ? private int viewWidth;//控件寬度
? ? private int distance;//文字高度
? ? private int pointX;//所有點的x坐標(biāo)
? ? private int pointY;//當(dāng)前點的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() {
? ? ? ? //計算文字高度
? ? ? ? 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 ? 二元一次方程,向左多畫一點計算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;
? ? ? ? ? ? //向右多畫一點,機制同上
? ? ? ? ? ? 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);
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android實現(xiàn)Camera2預(yù)覽和拍照效果
這篇文章主要為大家詳細(xì)介紹了Android開發(fā)之一個類實現(xiàn)Camera2預(yù)覽和拍照效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10
Flutter開發(fā)之設(shè)置應(yīng)用名稱及圖標(biāo)的教程
這篇文章主要介紹了Flutter設(shè)置應(yīng)用名稱及圖標(biāo)的方法,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-04-04
Retrofit網(wǎng)絡(luò)請求框架之注解解析和動態(tài)代理
這篇文章主要介紹了Retrofit網(wǎng)絡(luò)請求框架之注解解析和動態(tài)代理,Retrofit是目前Android平臺上比較流行的網(wǎng)絡(luò)請求框架之一,它提供了一種簡潔、靈活的方式來處理HTTP請求和響應(yīng)2023-03-03
Android中TextureView與SurfaceView用法區(qū)別總結(jié)
TextureView和SurfaceView都是繼承自View類的,TextureView在Andriod4.0之后才引入的,SurfaceView不能加上動畫、平移、縮放,TextureView可以但有1-3幀的延遲2018-04-04
Android官方下拉刷新控件SwipeRefreshLayout使用詳解
這篇文章主要為大家詳細(xì)介紹了Android官方下拉刷新控件SwipeRefreshLayout使用方法,實例展示如何使用下拉刷新控件,感興趣的小伙伴們可以參考一下2016-07-07
android 通過向viewpage中添加listview來完成滑動效果(類似于qq滑動界面)
android 通過向viewpage中添加listview來完成滑動效果(類似于qq滑動界面),需要的朋友可以參考一下2013-05-05

