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读取本地 ...
随机推荐
- appium通过同级别(兄弟关系)元素找到元素
在做appium测试用例的时候,要获取金额值,用uiautomatorviewer查看该元素,该元素没有特别明显的个性特点,唯一有特点的定位是有content-desc值,但是该值是变动的,所以无法通 ...
- msf web_delivery模块攻击
目标机:win7 ip:192.168.31.136 攻击机:kai liunx ip:192.168.31.54 一. ...
- kibana 的search 的的搜索提示挡住输入框
解决方案就是 [root@10-19-148-59 styles]# pwd /data/package/kibana/src/public/styles [root@10-19-148-59 sty ...
- 在 Visual Studio 2017 中找回消失的“在浏览器中查看”命令
不知为何,在新安装 Visual Studio 2017 后,发现所有 Web 项目上右键菜单的"在浏览器中查看"命令消失了,只能以调试模式启动网站,非常别扭. 最后在 Stack ...
- Android adb 命令速查表
常用命令 devices # 查看已连接的设备 start-server # 启动 adb server kill-server # 停止 adb server logcat # 查看日志 insta ...
- macbook中vagrant升级新版本
macbook由于缺少卸载机制,有时候不知道该如何升级软件. vagant的升级到时简单,经测试,只需直接官网下载新软件,安装即可. 旧版本不用管,新的会直接替换.
- Atitit 软件体系的进化,是否需要一个处理中心
Atitit 软件体系的进化,是否需要一个处理中心 1.1. 进化树上是没有主干的..1 1.2. ,软件进化的行为1::主要就是给新的应用编写新的程序.1 1.3. ,软件进化的行为2::软件的维护 ...
- GMap.net控件学习记录
主要参考网址 http://www.cnblogs.com/luxiaoxun/p/3802559.html http://www.cnblogs.com/luxiaoxun/p/3463250.ht ...
- DIOCP-开源项目ECHO测试.
DIOCP自开源以来,得到了很多朋友的测试,并进行了诸多的改进,现在已经运用到了一些具体的项目当中. DIOCP底层运行稳定. 昨天做了个ECHO测试,这个连接数并没有达到上限. 11K 连接,1个半 ...
- 【神经网络】Reducing the Dimensionality of Data with Neural Networks
这篇paper来做什么的? 用神经网络来降维.之前降维用的方法是主成分分析法PCA,找到数据集中最大方差方向.(附:降维有助于分类.可视化.交流和高维信号的存储) 这篇paper提出了一种非线性的PC ...