android 折线图滑动
来源:互联网 发布:淘宝购物车结算是灰的 编辑:程序博客网 时间:2024/06/05 19:43
android 折线图滑动 - 防小米天气24小时预报折线图
看到小米天气24小时预报,滑动的时候天气情况会跟着动,始终保持在显示区域中间,觉得很有趣,就试着写出来,顺便加深学习自定义view.
不多说废话了,先看效果图
一 .布局文件代码很简单如下,
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.zero.simplelinechart.HScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:fillViewport="true" android:scrollbars="none" android:id="@+id/HScrollView" android:layout_marginTop="50dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <com.zero.simplelinechart.LineChartView android:id="@+id/simpleLineChart" android:layout_width="match_parent" android:layout_height="150dp" android:background="@android:color/darker_gray" /> </LinearLayout> </com.zero.simplelinechart.HScrollView></LinearLayout>
二.LineChartView代码
这里面代码有点多,不过都有注释
主要就是些计算x轴点和y轴点
package com.zero.simplelinechart;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.DashPathEffect;import android.graphics.Paint;import android.graphics.Path;import android.util.AttributeSet;import android.util.Log;import android.view.View;import com.zero.simplelinechart.util.UtilApp;import java.util.ArrayList;/** * @author zero * 自定义动态折线图 */public class LineChartView extends View implements HScrollView.OnMyHScrollView{ private static final String TAG = "LineChartView"; private HScrollView mHScrollView; //Y轴 每个刻度的间距间距 private int myInterval = 5; //X轴 每个刻度的间距间距 private int mxInterval = 100; //Y轴距离view长度 private int mLeftInterval = 50; //X轴距离view长度 private int mBottomInterval = 50; //天气与X轴距离 private int mWeatherToXaxis = 20; //小短线与小圆点的距离 private int mLineToPoint = 10; //View 的宽和高 private int mWidth, mHeight; //Y轴字体的大小 private float mYAxisFontSize = 30; //线的颜色 private int mLineColor = Color.parseColor("#24c2f0"); //线条的宽度 private float mStrokeWidth = 4.0f; //温度与点的距离 private int TempToPoint = 12; //点的半径 private float mPointRadius = 5; //X轴的文字 (时间) private ArrayList<String> mXAxis; //点 (温度) private ArrayList<Integer> mYAxis; // 天气 private ArrayList<String> mWeather; //滑动的距离 private float mScrollLeft; public LineChartView(Context context) { this(context, null); } public LineChartView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public LineChartView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); //自定义view 像素 宽度和高度 Log.d(TAG,"widthSize:"+widthSize+",heightSize:"+heightSize ); //高度固定 150dp == 304 px mHeight =heightSize; if(mXAxis == null){ Log.d(TAG,"mWidth:"+mWidth+",mHeight:"+mHeight +"mXAxis:"+mXAxis); return; } //宽度通过数组长度计算 mWidth = mxInterval*(mXAxis.size()-1) + mLeftInterval*2; //1185dp 150dp setMeasuredDimension(mWidth, mHeight); } @Override protected void onDraw(Canvas canvas) { if(mXAxis.size()==0||mYAxis.size()==0){ Log.e(TAG,"数据异常"); return; } //画坐标线的轴 Paint axisPaint = new Paint(); axisPaint.setTextSize(mYAxisFontSize); axisPaint.setColor(Color.parseColor("#000000")); //画 X 轴 Paint xlinePaint = new Paint(); xlinePaint.setColor(mLineColor); xlinePaint.setAntiAlias(true); //设置线条宽度 xlinePaint.setStrokeWidth(mStrokeWidth); //画时间线条 canvas.drawLine(mLeftInterval,mHeight - mBottomInterval, (24-1)*mxInterval + mLeftInterval, mHeight - mBottomInterval, xlinePaint); //x轴的刻度集合 int[] xPoints = new int[mXAxis.size()]; for (int i = 0; i < mXAxis.size(); i++) { float timeWidth = axisPaint.measureText(mXAxis.get(i))/2 ; //时间宽度一半 float xfloat = i * mxInterval + mLeftInterval-timeWidth; //画时间 canvas.drawText(mXAxis.get(i), xfloat, mHeight - mBottomInterval+mYAxisFontSize, axisPaint); xPoints[i] = (int) (xfloat+timeWidth); } //画笔 圆点 Paint pointPaint = new Paint(); pointPaint.setColor(mLineColor); pointPaint.setStrokeWidth((float) 3.0); pointPaint.setStyle(Paint.Style.STROKE);// pointPaint.setStyle(Paint.Style.FILL); //画笔 线条 Paint linePaint = new Paint(); linePaint.setColor(mLineColor); linePaint.setAntiAlias(true); //设置线条宽度 linePaint.setStrokeWidth(mStrokeWidth); int count = 1; //相同天气个数 //屏幕宽度 int mScreenWidth = UtilApp.getScreenWidth(getContext()); for (int i = 0; i < mXAxis.size(); i++) { int xx = mYAxis.get(i) - mYAxis.get(0);//和第一个温度的差 int yAxisCentre = ( mHeight - mBottomInterval)/2; // Y轴中心点 if(xx != 0){ yAxisCentre = yAxisCentre - xx * myInterval; } //画圆点 canvas.drawCircle(xPoints[i], yAxisCentre, mPointRadius, pointPaint); int tempWidth = (int) axisPaint.measureText(""+mYAxis.get(i)); //温度字体宽度 //画温度 canvas.drawText(mYAxis.get(i)+"°", xPoints[i] - mPointRadius - tempWidth/2, yAxisCentre - mPointRadius - TempToPoint, axisPaint); int yAxisCentre2 = ( mHeight - mBottomInterval)/2; // Y轴中心点 int rightDifference = (int) (xPoints[i] - mScreenWidth - mScrollLeft);//右边看不见的点与屏幕的距离 if(0 == i){// //画虚线 第一条 PaintDashed(canvas, xPoints[i], (int) (yAxisCentre + mPointRadius), xPoints[i], mHeight - mBottomInterval ); }else if ( i < (mXAxis.size() - 1) ) { int xx2 = mYAxis.get(i-1) - mYAxis.get(0); if(xx2 != 0){ yAxisCentre2 = yAxisCentre2 - xx2 * myInterval; } //温度之间 短线 canvas.drawLine(xPoints[i - 1] + mLineToPoint, yAxisCentre2, xPoints[i] - mLineToPoint,yAxisCentre , linePaint); //画天气 画虚线 /** *虚线是天气区域的分割线 *从第二个天气开始 循环判断天气,不同的时候才 画虚线 画天气 * */ if(!mWeather.get(i).equals(mWeather.get(i-1))){ //画虚线 PaintDashed(canvas, xPoints[i], (int) (yAxisCentre + mPointRadius), xPoints[i], mHeight - mBottomInterval ); float weatherFontSize = axisPaint.measureText(mWeather.get(i-count));//天气字体宽度 if(mScrollLeft > mLeftInterval){ //左边 滑动大于边距50时候 天气移动 始终在在中间 if(xPoints[i] - mScrollLeft < count*mxInterval){ if(mScrollLeft< xPoints[i] - weatherFontSize){ //判断当天气移动到虚线边界时候 就不移动 float is2 = (xPoints[i-count] + count*mxInterval- mScrollLeft)/2+mScrollLeft; canvas.drawText(mWeather.get(i-count),is2 - mYAxisFontSize,mHeight - mBottomInterval - mWeatherToXaxis, axisPaint); // 20 天气字体与x轴距离 } else{ canvas.drawText(mWeather.get(i-count),xPoints[i] - weatherFontSize,mHeight - mBottomInterval - mWeatherToXaxis, axisPaint); } }else if(rightDifference > 0){// 右边天气位置 滑动时候 if(mScreenWidth + mScrollLeft > xPoints[i - count] + weatherFontSize){//判断当天气移动到虚线边界时候 就不移动 float x = mScreenWidth + mScrollLeft - (count * mxInterval - rightDifference)/2; canvas.drawText(mWeather.get(i - count), x - mYAxisFontSize, mHeight - mBottomInterval - mWeatherToXaxis, axisPaint); }else{ canvas.drawText(mWeather.get(i-count),xPoints[i - count],mHeight - mBottomInterval - mWeatherToXaxis, axisPaint); } }else{//天气位置 中间天气区域 canvas.drawText(mWeather.get(i - count), xPoints[i - count] + count * mxInterval / 2 - mYAxisFontSize, mHeight - mBottomInterval - mWeatherToXaxis, axisPaint); } }else { //天气位置 初始化 没有滑动时候 canvas.drawText(mWeather.get(i - count) , xPoints[i - count] + count * mxInterval / 2 - mYAxisFontSize, mHeight - mBottomInterval - mWeatherToXaxis, axisPaint); } count = 1; }else{ count = count+1; //每个时间段天气相同就加1 } }else if((mXAxis.size()-1) == i){ //最后一个区域 float weatherFontSize = axisPaint.measureText(mWeather.get(i));//天气字体宽度 //温度之间 短线 canvas.drawLine(xPoints[i - 1] + mLineToPoint, yAxisCentre2, xPoints[i] - mLineToPoint,yAxisCentre , linePaint); //画天气 最后一个天气区域 if(rightDifference > 0){// //最有右边天气位置 滑动时候 if(mScreenWidth + mScrollLeft > xPoints[i - count] + weatherFontSize){ float x = mScreenWidth + mScrollLeft - (count * mxInterval - rightDifference)/2; canvas.drawText(mWeather.get(i - count) , x - mYAxisFontSize, mHeight - mBottomInterval - mWeatherToXaxis, axisPaint); }else{ canvas.drawText(mWeather.get(i-count),xPoints[i - count],mHeight - mBottomInterval - mWeatherToXaxis, axisPaint); } }else{ canvas.drawText(mWeather.get(i - count) , xPoints[i - count] + count * mxInterval / 2 - mYAxisFontSize, mHeight - mBottomInterval - mWeatherToXaxis, axisPaint); } //画虚线 最后一条 PaintDashed(canvas, xPoints[i], (int) (yAxisCentre + mPointRadius), xPoints[i], mHeight - mBottomInterval ); } } } /** * 画虚线 * @param canvas * @param moveToX * @param moveToY * @param lineToX * @param lineToY */ private void PaintDashed ( Canvas canvas, int moveToX, int moveToY, int lineToX, int lineToY){ DashPathEffect pathEffect = new DashPathEffect(new float[] { 6,4 }, 0); Paint paint = new Paint(); paint.reset(); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(2); paint.setColor(Color.WHITE); paint.setAntiAlias(true); paint.setPathEffect(pathEffect); Path path = new Path(); path.moveTo(moveToX, moveToY); path.lineTo(lineToX, lineToY); canvas.drawPath(path, paint); } /** * 设置Y轴文字 温度值 * @param yItem */ public void setYItem(ArrayList<Integer> yItem){ mYAxis = yItem; } /** * 设置X轴文字 * @param xItem */ public void setXItem(ArrayList xItem){ mXAxis = xItem; } /** * 设置天气 * @param weather */ public void setWeather(ArrayList weather){ mWeather = weather; } public void setLineColor(int color){ mLineColor = color; invalidate(); } /** * * @param mHScrollView */ public void setmHScrollView(HScrollView mHScrollView) { Log.d("SimpleLineChart2", "mHScrollView:"+mHScrollView); if(mHScrollView == null){ return; } this.mHScrollView = mHScrollView; this.mHScrollView.setmOnMyHScrollView(this); } /** * 监听滑动事件(主要用到与左边的滑动距离) * @param l * @param t * @param oldl * @param oldt */ @Override public void onMyScrollChanged(int l, int t, int oldl, int oldt) {// Log.d(TAG, "l:" + l+",t:" + t+",oldl:" + oldl+",oldt:" + oldt); this.mScrollLeft = l; invalidate(); }}
三.项目源码下载
点击下载
0 0
- android 折线图滑动
- 自定义android折线图,实现左右滑动和快速滑动
- Android自定义折线图,可左右滑动,可点击
- Android使用highcharts实现可左右滑动的折线图
- Unity滑动折线图开发
- 横向滑动的折线图
- angularjs自定义折线图+滑动条指令
- 可缩放、滑动显示的折线图
- 可滑动折线图功能实现
- android 自定义折线图
- android 自定义折线图
- Android 折线图
- android 绘制折线图
- android 自定义 折线图
- android 动态折线图
- android绘制折线图
- android 自定义折线图
- android绘制折线图
- Python的yield相关理解
- redis笔记2--数据持久化和集群
- 【0.43】React Native 中文更新日志
- 位运算相关知识
- Android代码混淆
- android 折线图滑动
- sessionStorage和localStorage
- SQL(三)
- 利用SCP和CRT部署项目步骤详解
- Linux下的权限管理和ACM时间
- svn服务器搭建
- 10,USB 规范和验证
- react教程集
- ExtJS——TreePanel