创建自定义控件3-可交互性

2024-03-31 08:48

本文主要是介绍创建自定义控件3-可交互性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

绘制UI仅仅是创建自定义视图的一部分。除此之外,你还需要以一种非常接近现实世界行为的方式来响应用户的输入。所有的对象都应该表现得像现实世界的对象那样。例如,图片不应该突然消失后又出现在别的地方,因为现实中的物体是不会那样的。合乎情理的做法是它应该从一个位置移动到另一个位置。 用户要么体验到UI中精细的操作,要么仅仅感觉到只是界面,相比较而言前者模拟的现实世界会获得最好的用户体验。例如,当用户在操作UI的时候,他们一旦感到界面的滑动响应延迟,将会感到烦躁而疯狂的滑动屏幕。

这篇文章展示了如何结合Android框架的特点来增添现实世界的行为到你所定制的视图中。

处理输入手势-Handle Input Gestures


跟许多其它的UI框架一样,Android也支持输入事件模型。用户的操作会转变成触发回调函数的事件,你可以重写这个回调函数来定制你的应用如何响应用户。在Android系统中最常用的输入事件是触摸事件,它会触发onTouchEvent(android.view.MotionEvent),重写该方法可以处理该事件:

1
2
3
4
@Override   
public boolean onTouchEvent(MotionEvent event) {    
return super.onTouchEvent(event);  
}

触摸事件本身并不是特别的有用。现在的可触摸UI可以接受许多种手势动作的交互,如 轻拍、拉、推、摇动和缩放。Android系统提供了GestureDetector类,将基本的触摸事件转变成各种不同的手势动作。 通过实现GestureDetector.OnGestureListener接口来构造一个GestureDetector的一个实例。如果你仅仅只是想处理少部分的手势动作,你可以选择继承GestureDetector.SimpleOnGestureListener而不用去实现GestureDetector.OnGestureListener接口。例如,下面的代码就是创建了一个继承GestureDetector.SimpleOnGestureListener的类并重写了onDown(MotionEvent)方法。

1
2
3
4
5
6
7
class mListener extends GestureDetector.SimpleOnGestureListener {   
@Override   
public boolean onDown(MotionEvent e) {       return true;   
}
}
mDetector = new GestureDetector(PieChart.this.getContext(),new mListener());

不管你是否使用了GestureDetector.SimpleOnGestureListener类,你都必须要实现onDown()方法并返回true。这一步是必须的因为所有的触摸操作都从onDown() 方法中的事件开始。如果你在onDown()方法中返回false,就像GestureDetector.SimpleOnGestureListener所设计的那样,系统会认为你不需要其它的手势操作,那么GestureDetector.OnGestureListener接口的其余方法都不会被调用。唯一能够将onDown()方法返回false的情况就是你真的想忽略所有的手势操作。一旦你实现了GestureDetector.OnGestureListener接口并且创造了GestureDetector类的一个实例,你就可以用GestureDetector类来完成你在 onTouchEvent()方法中接收的触屏事件。

 123456789
10
11
@Override
public boolean onTouchEvent(MotionEvent event) {   
boolean result = mDetector.onTouchEvent(event);   
if (result) {       
if(event.getAction()==MotionEvent.ACTION_UP){           
stopScrolling();           
result = true;       
}   
}   return result;
}

当你想执行onTouchEvent()方法中的触摸事件而并不想把它当作手势操作的一部分,那就要返回false。你可以执行你自定义的检测手势操作的代码。

创建让人感觉合理的操作-Create Physically Plausible Motion

手势动作是控制触摸屏设备的一种很强有力的方式,但是它会违背人的直觉而让人难以记住,除非它让人得到合理的结果。滑动手指就是一个很好的例子,用户用一根手指快速的在屏幕上滑动然后抬起。只有在UI的响应速度跟得上用户快速的滑动屏幕的频率的时候,这个手势操作才是有意义的,就像用户在推动一个飞轮并想让它旋转起来。

然而,模拟一种飞轮的感觉也是不平凡的。要想得到一个正确的飞轮运转模型是需要大量的物理和数学验证的。庆幸的是,Android提供了帮助类来模拟它以及别的操作行为。Scroller 类是处理具有飞轮风格手势操作的基类。 开始实现滑动操作时,要调用fling()并传入初始的速率和在X轴和Y轴上滑动的最小值和最大值。根据这个速率的值,你就可以用该值并通过GestureDetector类来为你计算。

1
2
3
4
5
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {   
mScroller.fling(currentX, currentY, velocityX / SCALE, velocityY / SCALE, minX, minY, maxX, maxY);   
postInvalidate();
}

提示: 尽管通过GestureDetector类计算出的速率在理论上是精确的,但是许多开发人员都感到用这个值会让滑动的动画太快。常用的办法就是将X和Y方向的速率除以4到8之间的某一个值。

调用fling()方法会建立滑动操作的物理模型。接下来,你需要适时的调用 Scroller.computeScrollOffset() 方法来更新Scroller类的数据。computeScrollOffset() 方法通过读取当前的时间并用物理模型计算当前的X坐标和Y坐标来更新Scroller对象的内部状态调用getCurrX() 和getCurrY()方法可以获取最新的X坐标和Y坐标。 大部分的视图通过直接调用scrollTo()方法改变Scroller对象的X坐标和Y坐标的值。但是图表是有一点不一样的,它用当前Y轴的坐标来设定图表的张开角度。

1
2
3
4
if (mScroller.isFinished()) {mScroller.computeScrollOffset();setPieRotation(mScroller.getCurrY());
}

Scroller类能为你计算出滚动轴的位置,但是它不能自动的为你的视图提供它们的坐标位置。你必须确保你获得并应用的坐标在正常情况下足以能让滚动动画看起来流畅。这里有两种方法可以实现:

    • 为了能重绘视图,在调用fling()之后要调用postInvalidate()。这种技术需要你每次在补偿滚动轴的变化时要在onDraw()方法中计算滚动轴的变化并调用postInvalidate()方法。
    • 建立一个ValueAnimator来动态模拟滑动动作持续的状态,然后调用addUpdateListener()来添加一个监听者进行动画的更新。

图表用的就是第二种方法。这种方法在创建的时候略微会显得更加复杂,但是它工作起来会跟动画系统配合得更密切而且不需要可能不必要的无效视图。它的缺憾就是在低于API11的版本上ValueAnimator是不可用的,所以这种方法是不能用在低于Android3.0系统的设备上的。

提示:ValueAnimator虽然在低于API11的版本不可用,但是你仍然可以在你的应用程序中使用这个类并标上API版本过低。在程序运行的时候你必须确保检查了当前的API版本,如果当前的API版本低于11,在视图动画系统中就要忽略这些调用。

 123456789
10
11
12
13
14
mScroller = new Scroller(getContext(), null, true);
mScrollAnimator = ValueAnimator.ofFloat(0,1);
mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {           
@Override           
public void onAnimationUpdate(ValueAnimator valueAnimator) {               
if(mScroller.isFinished()){                   
mScroller.computeScrollOffset();
setPieRotation(mScroller.getCurrY());               
} else {                   
mScrollAnimator.cancel();                   
onScrollFinished();               
}           
}       
});

让你的界面流畅地转换

用户期望现代的UI能流畅的在状态之间转换。UI元素的淡入淡出会取代直接的出现和消失。各种操作都会按照自然的方式开始和结束而不是突然的启动和停止。在Android3.0系统中引入的property animation framework框架,会让流畅的转换变得简单。 在使用动画系统时,每一个视图属性的改变都将会影响到视图的外观,所以不要直接去改变视图的属性。取而代之的是,你可以用ValueAnimator来实现你对视图属性的改变。在下面的例子中,修改当前在图表中选定的饼图饼片会导致整个图表旋转,以便让你选择的点集中在选定的切片上。ValueAnimator 会在一个短暂的时间内实现旋转的改变,而不是突然地改变旋转的状态。

1
2
3
4
mAutoCenterAnimator = ObjectAnimator.ofInt(PieChart.this,"PieRotation",0); 
mAutoCenterAnimator.setIntValues(targetAngle);
mAutoCenterAnimator.setDuration(AUTOCENTER_ANIM_DURATION);
mAutoCenterAnimator.start();

如果你想改变基本的View 中的一个属性值,不如去改变视图动画,因为视图中有一个嵌入的ViewPropertyAnimator类,它对同步的多属性的动画做了优化。例如:

1
animate().rotation(targetAngle).setDuration(ANIM_DURATION).start();

这篇关于创建自定义控件3-可交互性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/863925

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Python创建Excel的4种方式小结

《Python创建Excel的4种方式小结》这篇文章主要为大家详细介绍了Python中创建Excel的4种常见方式,文中的示例代码简洁易懂,具有一定的参考价值,感兴趣的小伙伴可以学习一下... 目录库的安装代码1——pandas代码2——openpyxl代码3——xlsxwriterwww.cppcns.c

使用Python在Excel中创建和取消数据分组

《使用Python在Excel中创建和取消数据分组》Excel中的分组是一种通过添加层级结构将相邻行或列组织在一起的功能,当分组完成后,用户可以通过折叠或展开数据组来简化数据视图,这篇博客将介绍如何使... 目录引言使用工具python在Excel中创建行和列分组Python在Excel中创建嵌套分组Pyt

CSS自定义浏览器滚动条样式完整代码

《CSS自定义浏览器滚动条样式完整代码》:本文主要介绍了如何使用CSS自定义浏览器滚动条的样式,包括隐藏滚动条的角落、设置滚动条的基本样式、轨道样式和滑块样式,并提供了完整的CSS代码示例,通过这些技巧,你可以为你的网站添加个性化的滚动条样式,从而提升用户体验,详细内容请阅读本文,希望能对你有所帮助...

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时

MySQL分表自动化创建的实现方案

《MySQL分表自动化创建的实现方案》在数据库应用场景中,随着数据量的不断增长,单表存储数据可能会面临性能瓶颈,例如查询、插入、更新等操作的效率会逐渐降低,分表是一种有效的优化策略,它将数据分散存储在... 目录一、项目目的二、实现过程(一)mysql 事件调度器结合存储过程方式1. 开启事件调度器2. 创

mysql外键创建不成功/失效如何处理

《mysql外键创建不成功/失效如何处理》文章介绍了在MySQL5.5.40版本中,创建带有外键约束的`stu`和`grade`表时遇到的问题,发现`grade`表的`id`字段没有随着`studen... 当前mysql版本:SELECT VERSION();结果为:5.5.40。在复习mysql外键约

Window Server创建2台服务器的故障转移群集的图文教程

《WindowServer创建2台服务器的故障转移群集的图文教程》本文主要介绍了在WindowsServer系统上创建一个包含两台成员服务器的故障转移群集,文中通过图文示例介绍的非常详细,对大家的... 目录一、 准备条件二、在ServerB安装故障转移群集三、在ServerC安装故障转移群集,操作与Ser

Window Server2016 AD域的创建的方法步骤

《WindowServer2016AD域的创建的方法步骤》本文主要介绍了WindowServer2016AD域的创建的方法步骤,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、准备条件二、在ServerA服务器中常见AD域管理器:三、创建AD域,域地址为“test.ly”

C#实现WinForm控件焦点的获取与失去

《C#实现WinForm控件焦点的获取与失去》在一个数据输入表单中,当用户从一个文本框切换到另一个文本框时,需要准确地判断焦点的转移,以便进行数据验证、提示信息显示等操作,本文将探讨Winform控件... 目录前言获取焦点改变TabIndex属性值调用Focus方法失去焦点总结最后前言在一个数据输入表单