Android開發(fā)RecyclerView實(shí)現(xiàn)折線圖效果
本文實(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);
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實(shí)現(xiàn)RecyclerView嵌套流式布局的詳細(xì)過程
- Android RecyclerView實(shí)現(xiàn)吸頂動(dòng)態(tài)效果流程分析
- Android RecyclerView四級(jí)緩存源碼層詳細(xì)分析
- Android RecyclerView緩存復(fù)用原理解析
- Android RecyclerView使用入門介紹
- Android開發(fā)RecyclerView單獨(dú)刷新使用技巧
- Android?手寫RecyclerView實(shí)現(xiàn)列表加載
- Android獲取RecyclerView滑動(dòng)距離方法詳細(xì)講解
相關(guān)文章
Android開發(fā)實(shí)現(xiàn)錄屏小功能
這篇文章主要介紹了Android開發(fā)實(shí)現(xiàn)錄屏小功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07Android實(shí)現(xiàn)Camera2預(yù)覽和拍照效果
這篇文章主要為大家詳細(xì)介紹了Android開發(fā)之一個(gè)類實(shí)現(xiàn)Camera2預(yù)覽和拍照效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Flutter開發(fā)之設(shè)置應(yīng)用名稱及圖標(biāo)的教程
這篇文章主要介紹了Flutter設(shè)置應(yīng)用名稱及圖標(biāo)的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04Retrofit網(wǎng)絡(luò)請求框架之注解解析和動(dòng)態(tài)代理
這篇文章主要介紹了Retrofit網(wǎng)絡(luò)請求框架之注解解析和動(dòng)態(tài)代理,Retrofit是目前Android平臺(tái)上比較流行的網(wǎng)絡(luò)請求框架之一,它提供了一種簡潔、靈活的方式來處理HTTP請求和響應(yīng)2023-03-03Android中TextureView與SurfaceView用法區(qū)別總結(jié)
TextureView和SurfaceView都是繼承自View類的,TextureView在Andriod4.0之后才引入的,SurfaceView不能加上動(dòng)畫、平移、縮放,TextureView可以但有1-3幀的延遲2018-04-04Android官方下拉刷新控件SwipeRefreshLayout使用詳解
這篇文章主要為大家詳細(xì)介紹了Android官方下拉刷新控件SwipeRefreshLayout使用方法,實(shí)例展示如何使用下拉刷新控件,感興趣的小伙伴們可以參考一下2016-07-07android 通過向viewpage中添加listview來完成滑動(dòng)效果(類似于qq滑動(dòng)界面)
android 通過向viewpage中添加listview來完成滑動(dòng)效果(類似于qq滑動(dòng)界面),需要的朋友可以參考一下2013-05-05