android开发(29) 自定义曲线,可拖动,无限加载
项目需要 做一个曲线,该曲线的数据时不断加载的。如下图,当不断向左拖动时,图形曲线要随着拖动移动,并在拖动到边界时需要加载更多数据。
先看步骤:
1.在Activity里放一个surfaceView
2.为surfaceView 添加监听器
surfaceHolder = surfaceView1.getHolder();
mMySurfaceCallback = new MySurfaceCallback();
surfaceHolder.addCallback(mMySurfaceCallback);
3.实现监听器。
class MySurfaceCallback implements android.view.SurfaceHolder.Callback {
MyDraw mMyDraw; @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
mMyDraw.onSurfaceChanged();
} @Override
public void surfaceCreated(SurfaceHolder holder) {
mMyDraw = new MyDraw();
mMyDraw.draw();
} @Override
public void surfaceDestroyed(SurfaceHolder holder) { } }
4.编写绘制图形的方法
class MyDraw {
Paint p;
Canvas canvas; int unit_x = 80; // 单位 宽度,根据要 绘制的个数不同而计算
int unit_y = 10;// 单位高度 ,固定 final int preInit_x = 50;// 开始位置
final int preInit_y = 550;// 最大的Y顶点。 Point origin; final int MAX_Fliing_X = unit_x * 20;// 最大20个 public MyDraw() {
super();
p = new Paint(); // 创建画笔 origin = new Point(preInit_x, preInit_y);// 坐标系的原点
} /**
* 拖动的范围,x > 0说明是 从左到右拖动。 x<0是从右向左拖动
*
* @param x_changed
*/
public void onFliing(float x_changed) {
float newX = origin.x + x_changed;
if (newX > preInit_x)
newX = preInit_x;
int minNewX = -((result.length) * unit_x - surfaceView1.getWidth());
boolean isToEnd = false;// 是否到达了最后一个点。即拖到最右侧极限处。
if (newX < minNewX) {
newX = minNewX;
isToEnd = true;
}
int x = (int) newX;
if (x == origin.x)
return;
origin = new Point(x, origin.y);//更改坐标系原点的位置
draw(); if (isToEnd) {// 触发 到达顶点的方法。
raiseScrollToEnd();
}
} public void draw() {
canvas = surfaceHolder.lockCanvas();
onDdraw(canvas);
surfaceHolder.unlockCanvasAndPost(canvas);
} public void onDdraw(Canvas c) {
Log.i("PDWY", String.format("新原点位置 :(%s, %s)", origin.x, origin.y)); Rect r; int height = c.getHeight();
int width = c.getWidth(); c.drawColor(Color.BLACK); p.setColor(Color.RED);
p.setStrokeWidth(2);
p.setStyle(Paint.Style.STROKE);
r = new Rect(2, 2, width - 2, height - 2);
c.drawRect(r, p); p.reset();
p.setColor(Color.RED);
p.setStrokeWidth(5); float[] lines = new float[max_unit];
lines = evalPosition(result, unit_x, unit_y, origin);
// lines = new float[]{0,0,50,500,100,400,100,400,150,500,0,0};
// drawLines方法用一组float表示要绘制的直线,每个直线用4个点表示,前两个为起端点,后两个为终端点
c.drawLines(lines, 2, lines.length - 2, p);
p.reset();
p.setColor(Color.parseColor("#dcdcdc"));
drawEndPoint(lines, 2, lines.length - 2, p, c);
} private void drawEndPoint(float[] lines, int offset, int count,
Paint p2, Canvas c) {
for (int i = offset; i < count; i += 2) {
float x = lines[i];
float y = lines[i + 1];
c.drawCircle(x, y, 8, p2);
}
} private float[] evalPosition(float[] result2, int unit_widht,
int unit_height, Point origin) {
if (result2 == null)
return new float[0];
float[] val = new float[result2.length * 4]; for (int i = 0; i < result2.length; i++) {
float y = origin.y - result2[i] * unit_height;
float x = origin.x + unit_widht * i; val[i * 4 + 0] = x;
val[i * 4 + 1] = y;
val[i * 4 + 2] = x;
val[i * 4 + 3] = y;
}
return val;
} final int max_unit = 6; public void onSurfaceChanged() { }
}
5. 注册 手势 ,当手指拖动时,曲线要随着变化。
surfaceView1.setOnTouchListener(new OnTouchListener() {
int state = 0;
float x_start; @Override
public boolean onTouch(View v, MotionEvent event) {
// mGestureDetector.onTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
state = 1;
x_start = event.getX();
}
if (event.getAction() == MotionEvent.ACTION_UP) {
state = 0;
x_start = 0;
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (state == 1) {
if (mMySurfaceCallback != null
&& mMySurfaceCallback.mMyDraw != null) {
float xEnd = event.getX();
float x_changed = (float) ((xEnd - x_start) / 1.3);
if (Math.abs(x_changed) > 5) {
Log.i("PDWY", "移动了 " + x_changed);
mMySurfaceCallback.mMyDraw.onFliing(x_changed); x_start = xEnd;
}
}
}
}
return true;
}
});
6。记得计算坐标位置,当不断向左拖动,拖动到 最后时,触发一个 自定义的 事件 onScrollToEnd。订阅了该事件的对象可以在 适当的时机 “加载更多的数据”
/**
* 拖动的范围,x > 0说明是 从左到右拖动。 x<0是从右向左拖动
*
* @param x_changed
*/
public void onFliing(float x_changed) {
float newX = origin.x + x_changed;
if (newX > preInit_x)
newX = preInit_x;
int minNewX = -((result.length) * unit_x - surfaceView1.getWidth());
boolean isToEnd = false;// 是否到达了最后一个点。即拖到最右侧极限处。
if (newX < minNewX) {
newX = minNewX;
isToEnd = true;
}
int x = (int) newX;
if (x == origin.x)
return;
origin = new Point(x, origin.y);//更改坐标系原点的位置
draw(); if (isToEnd) {// 触发 到达顶点的方法。
raiseScrollToEnd();
}
}
自定义事件的实现
ScrollToEndListener mScrollToEndListener; private void raiseScrollToEnd() {
if (mScrollToEndListener != null)
mScrollToEndListener.onScrollToEnd();
} public void setScrollToEndListener(ScrollToEndListener scrollToEndListener) {
mScrollToEndListener = scrollToEndListener;
} public static interface ScrollToEndListener {
public void onScrollToEnd();
}
-------------------------
最后,看看如何使用它:
public class MainActivity extends Activity {
SurfaceView surfaceView1; MyCustomCurve mMyCustomCurve; float[] result; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Package pck = Package.getPackage(this.getPackageName());
Resources resource = this.getResources(); surfaceView1 = (SurfaceView)findViewById(resource.getIdentifier("surfaceView1", "id", pck.getName())); mMyCustomCurve = new MyCustomCurve(this,surfaceView1); result = new float[] { 1, 30, 50, 40, 30, 5, 15, 35, 20,3,12,15,31, 30, 50, 40, 30, 5, 15, 35, 20,3,12,15,15};
mMyCustomCurve.setResult(result); //当读取到数据的终点时
mMyCustomCurve.setScrollToEndListener(new ScrollToEndListener() { @Override
public void onScrollToEnd() {
ArrayList<Float> lst = new ArrayList<Float>();
for (int i = 0; i < result.length; i++) {
lst.add(result[i]);
} //追加新的数据,随机添加10个数字,值不大于50.
Random r = new Random();
for (int j = 0; j < 10; j++) {
lst.add(r.nextFloat() * 50);
} float[] newArray = new float[lst.size()];
for (int i = 0; i < lst.size(); i++) {
newArray[i] = lst.get(i);
}
result = newArray;
//设置新的数据源
mMyCustomCurve.setResult(result);
Toast.makeText(MainActivity.this, "加载了一次新的数据", 0).show();
}
});
}
代码下载 提取码:883c
android开发(29) 自定义曲线,可拖动,无限加载的更多相关文章
- Vue.js 开发实践:实现精巧的无限加载与分页功能
本篇文章是一篇Vue.js的教程,目标在于用一种常见的业务场景--分页/无限加载,帮助读者更好的理解Vue.js中的一些设计思想.与许多Todo List类的入门教程相比,更全面的展示使用Vue.js ...
- 【Android开发那点破事】打开APP加载页面实现
今天的破事呢就说说APP加载页面的实现.一般情况下,当APP打开的时候,我们需要做很多事情,比如检查网络连接啊,初始化一些配置啊等等.我们可以让这些事情在APP完全打开之前做完,然后呢在打开的过程中显 ...
- android开发之自定义组件
android开发之自定义组件 一:自定义组件: 我认为,自定义组件就是android给我们提供的的一个空白的可以编辑的图片,它帮助我们实现的我们想要的界面,也就是通过自定义组件我们可以把我们要登入的 ...
- JRoll 2 使用文档(史上最强大的下拉刷新,滚动,无限加载插件)
概述 说明 JRoll,一款能滚起上万条数据,具有滑动加速.回弹.缩放.滚动条.滑动事件等功能,兼容CommonJS/AMD/CMD模块规范,开源,免费的轻量级html5滚动插件. JRoll第二版是 ...
- Qt实现小功能之列表无限加载(创意很不错:监听滚动条事件,到底部的时候再new QListWidgetItem)
概念介绍 无限加载与瀑布流的结合在Web前端开发中的效果非常新颖,对于网页内容具备较好的表现形式.无限加载并没有一次性将内容全部加载进来,而是通过监听滚动条事件来刷新内容的.当用户往下拖动滚动条或使用 ...
- Qt实现小功能之列表无限加载
概念介绍 无限加载与瀑布流的结合在Web前端开发中的效果非常新颖,对于网页内容具备较好的表现形式.无限加载并没有一次性将内容全部加载进来,而是通过监听滚动条事件来刷新内容的.当用户往下拖动滚动条或使用 ...
- Android系列之Fragment(一)----Fragment加载到Activity当中
Android上 的界面展示都是通过Activity实现的,Activity实在是太常用了.但是Activity也有它的局限性,同样的界面在手机上显示可能很好看, 在平板上就未必了,因为平板的屏幕非常 ...
- Android UI--自定义ListView(实现下拉刷新+加载更多)
Android UI--自定义ListView(实现下拉刷新+加载更多) 关于实现ListView下拉刷新和加载更多的实现,我想网上一搜就一堆.不过我就没发现比较实用的,要不就是实现起来太复杂,要不就 ...
- Android图片管理组件(双缓存+异步加载)
转自:http://www.oschina.net/code/snippet_219356_18887?p=3#comments ImageManager2这个类具有异步从网络下载图片,从sd读取本地 ...
随机推荐
- Java – How to convert a primitive Array to List
Java – How to convert a primitive Array to ListCode snippets to convert a primitive array int[] to a ...
- 验证码识别 图像降噪 Python (一)
原始图片: 降噪后的图片 实现代码: # coding:utf-8 import sys, os from PIL import Image, ImageDraw # 二值数组 t2val = {} ...
- js前台取用后台传递过来的map集合方式
在处理有些特殊需求的时候,我们需要在前台页面的js中获取后台传递过来的map集合类型的参数,并且进行调用,代码如下: 在后台我们拼装出如下的集合: Map<String,Grade> gr ...
- kafka 配置文件注释
文章转载自:http://liyonghui160com.iteye.com/blog/2163899 server.properties配置: server.properties中所有配置参数说明( ...
- MySql(五):MySQL数据库安全管理
一.前言 对于任何一个企业来说,其数据库系统中所保存数据的安全性无疑是非常重要的,尤其是公司的有些商业数据,可能数据就是公司的根本. 失去了数据,可能就失去了一切 本章将针对mysql的安全相关内容进 ...
- activiti并行和串行区别
多实例还有并行.串行区分.以下解释一下什么是并行与串行 并行代表同时进行,如把任务分给5个人来处理,这5个人同时会收到任务,并且可以同时处理,不受各自的影响. 串行代表工作或任务由一个人完成后,再由另 ...
- Android4.1(Jelly Bean)API新特性尝鲜
原文:http://android.eoe.cn/topic/android_sdk Android 4.1 APIs (API Level: 16)http://developer.android. ...
- Android 控件: Webview 的一些知识点
WebView 加载网页,当点击返回键的时,会显示上一个页面,并刷新. 同时可以对返回上一个页面进行干预,就是用到了缓存. webview加载网页的几个模式,即websetting中设置的加载模式.w ...
- 开源企业IM-免费企业即时通讯-ENTBOOST V2014.180 Windows版本号正式公布
ENTBOOST,VERSION 2014.180 Linux版本号公布,主要添加企业IM应用集成功能,完好安卓SDK功能及部分BUG修正. 下一版本号公布时间.7月15日.敬请关注. ENTBOOS ...
- Vivado下生成及烧写MCS文件
Jtag模式: 1.打开Open Hardware Manager 2. Tools ->Auto Connect 3.TCL输入: write_cfgmem -format MCS -size ...