android的一些控件
原来朋友给过的一个 显示时间的 样例,还能够改动时间,可是要机子有root权限才干改动。
在这个时间表盘的样例基础上 改动改动 图片。背景图什么的 就能够达到自己想要的效果了。。
下载地址: http://download.csdn.net/detail/kongbaidepao/8090083
1个风车效果的样例
是依据手滑动的速度 转动快慢的
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva29uZ2JhaWRlcGFv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
代码不多,直接粘过来
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RotatView rotatView=(RotatView)findViewById(R.id.myRotatView);
rotatView.setRotatDrawableResource(R.drawable.cycle);
}
}
public class RotatView extends View {
//原心坐标x
float o_x;
float o_y;
/**
* 处理惯性的handler
*/
Handler handler;
//handler处理消息的间隔
int delayedTime = 20;
/**
* 消息信号,滚动的标识
*/
static final int play = 0;
/**
* 消息信号,停止滚动的标识
*/
static final int stop = 1;
/**
* 上次记录的时间,计算一定时间所走过的弧度、计算速度.
*/
double currentTime = 0;
/**
* 图片的宽度
*/
int width;
/**
* 图片的高度
*/
int height;
/**
* view的真实宽度与高度:由于是旋转。所以这个view是正方形,它的值是图片的对角线长度
*/
double maxwidth;
/**
* 旋转的图片
*/
Bitmap rotatBitmap;
public RotatView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
/**
* 初始化handler与速度计算器
*/
private void init() {
vRecord = new VRecord();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
double detaTime = System.currentTimeMillis() - currentTime;
switch (msg.what) {
case play: {
if (isClockWise) {
speed = speed - a * detaTime;
if (speed <= 0) {
return;
} else {
handler.sendEmptyMessageDelayed(play, delayedTime);
}
} else {
speed = speed + a * detaTime;
if (speed >= 0) {
return;
} else {
handler.sendEmptyMessageDelayed(play, delayedTime);
}
}
addDegree((float)(speed * detaTime + (a * detaTime * detaTime) / 2));
// if (a < a_max) {
// a = (float)(a + a_add*detaTime);
// System.out.println("a:"+a);
// }
currentTime = System.currentTimeMillis();
invalidate();
break;
}
case stop: {
speed = 0;
handler.removeMessages(play);
}
}
super.handleMessage(msg);
}
};
// 默认是有一张图片的
initSize();
}
public void setRotatBitmap(Bitmap bitmap) {
rotatBitmap = bitmap;
initSize();
postInvalidate();
}
public void setRotatDrawableResource(int id) {
BitmapDrawable drawable = (BitmapDrawable)getContext().getResources().getDrawable(id);
setRotatDrawable(drawable);
}
public void setRotatDrawable(BitmapDrawable drawable) {
rotatBitmap = drawable.getBitmap();
initSize();
postInvalidate();
}
private void initSize() {
if (rotatBitmap == null) {
// throw new NoBitMapError("Error,No bitmap in RotatView!");
return;
}
width = rotatBitmap.getWidth();
height = rotatBitmap.getHeight();
maxwidth = Math.sqrt(width * width + height * height);
o_x = o_y = (float)(maxwidth / 2);//确定圆心坐标
}
/**
* 通过此方法来控制旋转度数,假设超过360,让它求余,防止,该值过大造成越界
*
* @param added
*/
private void addDegree(float added) {
deta_degree += added;
if (deta_degree > 360 || deta_degree < -360) {
deta_degree = deta_degree % 360;
}
}
@Override
protected void onDraw(Canvas canvas) {
Matrix matrix = new Matrix();
// 设置转轴位置
matrix.setTranslate((float)width / 2, (float)height / 2);
// 開始转
matrix.preRotate(deta_degree);
// 转轴还原
matrix.preTranslate(-(float)width / 2, -(float)height / 2);
// 将位置送到view的中心
matrix.postTranslate((float)(maxwidth - width) / 2, (float)(maxwidth - height) / 2);
canvas.drawBitmap(rotatBitmap, matrix,paint);
super.onDraw(canvas);
}
Paint paint=new Paint();
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 它的宽高不是图片的宽高,而是以宽高为直角的矩形的对角线的长度
setMeasuredDimension((int)maxwidth, (int)maxwidth);
}
/**
* 手指触屏的初始x的坐标
*/
float down_x;
/**
* 手指触屏的初始y的坐标
*/
float down_y;
/**
* 移动时的x的坐标
*/
float target_x;
/**
* 移动时的y的坐标
*/
float target_y;
/**
* 放手时的x的坐标
*/
float up_x;
/**
* 放手时的y的坐标
*/
float up_y;
/**
* 当前的弧度(以该 view 的中心为圆点)
*/
float current_degree;
/**
* 放手时的弧度(以该 view 的中心为圆点)
*/
float up_degree;
/**
* 当前圆盘所转的弧度(以该 view 的中心为圆点)
*/
float deta_degree;
/**
* 最后一次手势滑过的时间
*/
double lastMoveTime = 0;
/**
* 最小加速度(当手指放手是)
*/
public static final float a_min = 0.001f;
/**
* 加速度增量
*/
public static final float a_add = 0.001f;
/**
* 加速度
*/
float a = a_min;
/**
* 最大加速度(当手指按住时)
*/
public static final float a_max = a_min * 5;
/**
* 旋转速度(度/毫秒)
*/
double speed = 0;
/**
* 速度计算器
*/
VRecord vRecord;
/**
* 是否为顺时针旋转
*/
boolean isClockWise;
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if (rotatBitmap == null) {
throw new NoBitMapError("Error,No bitmap in RotatView!");
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
down_x = event.getX();
down_y = event.getY();
current_degree = detaDegree(o_x, o_y, down_x, down_y);
vRecord.reset();
// handler.sendEmptyMessage(stop);
a = a_max;
break;
}
case MotionEvent.ACTION_MOVE: {
down_x = target_x = event.getX();
down_y = target_y = event.getY();
float degree = detaDegree(o_x, o_y, target_x, target_y);
// 滑过的弧度增量
float dete = degree - current_degree;
// 假设小于-90度说明 它跨周了,须要特殊处理350->17,
if (dete < -270) {
dete = dete + 360;
// 假设大于90度说明 它跨周了,须要特殊处理-350->-17,
} else if (dete > 270) {
dete = dete - 360;
}
lastMoveTime = System.currentTimeMillis();
vRecord.add(dete, lastMoveTime);
addDegree(dete);
current_degree = degree;
postInvalidate();
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
a = a_min;
double lastupTime = System.currentTimeMillis();
double detaTime = lastupTime - lastMoveTime;
up_x = event.getX();
up_y = event.getY();
up_degree = detaDegree(o_x, o_y, up_x, up_y);
// 放手时的速度
speed = speed + vRecord.getSpeed();
if (speed > 0) {
speed = Math.min(VRecord.max_speed, speed);
} else {
speed = Math.max(-VRecord.max_speed, speed);
}
// System.out.println("speed:" + speed);
if (speed > 0) {
isClockWise = true;
// v = 1;
} else {
isClockWise = false;
// v = -1;
}
currentTime = System.currentTimeMillis();
handler.sendEmptyMessage(0);
break;
}
}
return true;
}
/**
* 计算以(src_x,src_y)为坐标圆点,建立直角体系,求出(target_x,target_y)坐标与x轴的夹角
* 主要是利用反正切函数的知识求出夹角
*
* @param src_x
* @param src_y
* @param target_x
* @param target_y
* @return
*/
float detaDegree(float src_x, float src_y, float target_x, float target_y) {
float detaX = target_x - src_x;
float detaY = target_y - src_y;
double d;
if (detaX != 0) {
float tan = Math.abs(detaY / detaX);
if (detaX > 0) {
if (detaY >= 0) {
d = Math.atan(tan);
} else {
d = 2 * Math.PI - Math.atan(tan);
}
} else {
if (detaY >= 0) {
d = Math.PI - Math.atan(tan);
} else {
d = Math.PI + Math.atan(tan);
}
}
} else {
if (detaY > 0) {
d = Math.PI / 2;
} else {
d = -Math.PI / 2;
}
}
return (float)((d * 180) / Math.PI);
}
/**
* 一个异常。用来推断是否有rotatbitmap
*
* @author sun.shine
*/
static class NoBitMapError extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 1L;
public NoBitMapError(String detailMessage) {
super(detailMessage);
}
}
/**
* 速度计算器 原来是将近期的 弧度增量和时间点记录下来,然后<br>
* 通过增量除以总时间求出平均值做为它的即时手势滑过的速度
*
* @author sun.shine
*/
static class VRecord {
/**
* 数组中的有效数字
*/
int addCount;
/**
* 最大能装的数据空间
*/
public static final int length = 15;
/**
* 二维数组,1.保存弧度增量.2.保存产生这个增量的时间点
*/
double[][] record = new double[length][2];
/**
* 为二维数组装载数据<br>
* 注:通过此方法,有个特点,能把最后的length组数据记录下来,length以外的会丢失
*
* @param detadegree
* @param time
*/
public void add(double detadegree, double time) {
for (int i = length - 1; i > 0; i--) {
record[i][0] = record[i - 1][0];
record[i][1] = record[i - 1][1];
}
record[0][0] = detadegree;
record[0][1] = time;
addCount++;
}
/**
* 最大速度
*/
public static final double max_speed = 8;
/**
* 通过数组里所装载的数据分析出即时速度<br>
* 原理是:计算数组里的时间长度和增量的总数。然后求出每毫秒所走过的弧度<br>
* 当然不能超过{@link VRecord#max_speed}
*
* @return
*/
public double getSpeed() {
if (addCount == 0) {
return 0;
}
int maxIndex = Math.min(addCount, length) - 1;
if ((record[0][1] - record[maxIndex][1]) == 0) {
return 0;
}
double detaTime = record[0][1] - record[maxIndex][1];
double sumdegree = 0;
for (int i = 0; i < length - 1; i++) {
sumdegree += record[i][0];
// System.out.println(record[i][0]);
}
// System.out.println("----------");
// System.out.println(sumdegree);
// System.out.println(detaTime);
double result = sumdegree / detaTime;
if (result > 0) {
return Math.min(result, max_speed);
} else {
return Math.max(result, -max_speed);
}
// System.out.println("v=" + result);
}
/**
* 重置
*/
public void reset() {
addCount = 0;
for (int i = length - 1; i > 0; i--) {
record[i][0] = 0;
record[i][1] = 0;
}
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if(rotatBitmap!=null){
rotatBitmap.recycle();
rotatBitmap=null;
}
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ffffffff" > <com.sun.shine.myrotation.view.RotatView
android:id="@+id/myRotatView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dip" >
</com.sun.shine.myrotation.view.RotatView> </RelativeLayout>
android的一些控件的更多相关文章
- Android 中常见控件的介绍和使用
1 TextView文本框 1.1 TextView类的结构 TextView 是用于显示字符串的组件,对于用户来说就是屏幕中一块用于显示文本的区域.TextView类的层次关系如下: java.la ...
- Android中ListView控件的使用
Android中ListView控件的使用 ListView展示数据的原理 在Android中,其实ListView就相当于web中的jsp,Adapter是适配器,它就相当于web中的Servlet ...
- 五、Android学习第四天补充——Android的常用控件(转)
(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 五.Android学习第四天补充——Android的常用控件 熟悉常用的A ...
- 注意Android里TextView控件的一个小坑,用android:theme来设置样式时动态载入的layout会丢失该样式
注意Android里TextView控件的一个小坑,用android:theme来设置样式时动态载入的layout会丢失该样式 这个坑,必须要注意呀, 比如在用ListView的时候,如果在List_ ...
- Android其它新控件 (转)
原文出处:http://blog.csdn.net/lavor_zl/article/details/51312715 Android其它新控件是指非Android大版本更新时提出的新控件,也非谷歌I ...
- Android 之计算控件颜色透明度
Android 之计算控件颜色透明度 1.UI会给一个数值,例如:#EFE000,透明度30% 2.用255乘以30%等于76.5,然后四舍五入等于77 3.用计算器将十进制的77转成十六进制的数据为 ...
- 【转】Android M新控件之AppBarLayout,NavigationView,CoordinatorLayout,CollapsingToolbarLayout的使用
Android M新控件之AppBarLayout,NavigationView,CoordinatorLayout,CollapsingToolbarLayout的使用 分类: Android UI ...
- 【转】Android M新控件之FloatingActionButton,TextInputLayout,Snackbar,TabLayout的使用
Android M新控件之FloatingActionButton,TextInputLayout,Snackbar,TabLayout的使用 分类: Android UI2015-06-15 16: ...
- android中ListView控件&&onItemClick事件中获取listView传递的数据
http://blog.csdn.net/aben_2005/article/details/6592205 本文转载自:android中ListView控件&&onItemClick ...
- 【风马一族_Android】第4章Android常用基本控件
第4章Android常用基本控件 控件是Android用户界面中的一个个组成元素,在介绍它们之前,读者必须了解所有控件的父类View(视图),它好比一个盛放控件的容器. 4.1View类概述 对于一个 ...
随机推荐
- 理解进程调度时机跟踪分析进程调度与进程切换的过程(Linux)
----------------------------------------------------------------------------------- 理解进程调度时机跟踪分析进程调度 ...
- springboot项目启动报错
启动springboot项目报错: NoSuchMethodError: org.apache.tomcat.util.scan.StandardJarScanner.setJarScanFilter ...
- 位图算法 C语言
#include <stdio.h> void set_bit(void *base, unsigned long n) { unsigned long *m = (unsigned lo ...
- How to set up OpenERP for various timezone kindly follow the following steps to select timezone in OpenERP
How to set up OpenERP for different Time Zones Click on the "Edit Preferences" wheel a ...
- Rational Rose 2003 逆向工程转换C++源代码成UML类图
主要介绍用户如何使用Rose的逆向工程生成UML模型,并用来进行C++代码的结构分析. Rational Rose可以支持标准C++和Visual C++的模型到代码的转换以及逆向工程.下面将详细地说 ...
- extends android.view.ViewGroup两种实现
/* private int measureHeight(int heightMeasureSpec) { int count = getChildCount(); ...
- docker login harbor出现的报错Error response from daemon: Get https://172.16.1.99/v1/users/: dial tcp 172.16.1.99:443: getsockopt: connection refused解决方法
出现的问题 [root@master01 ~]# docker login 172.16.1.99 Username: admin Password: Error response from daem ...
- Web Service-WSDL详解
WSDL指网络服务描述语言 (Web Services Description Language), 是一种用XML编写的文档, 用于描述Web Service和函数.参数以及返回值等; 文档内规定了 ...
- Falsk-信号
Flask框架中的信号基于blinker,其主要就是让开发者可是在flask请求过程中定制一些用户行为. 安装:pip3 install blinker request_started = _sign ...
- Megcup 2017 决赛第一题 规则
2017Megcup 2017Megcup决赛第三题题解 只做出了一道题,虽然慢慢地退出了前128名,但还是要记录一下. 10点钟开始,一看第一题很熟悉,因为研究过格点图中电流问题,其实就是求解线性方 ...