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类概述 对于一个 ... 
随机推荐
- ImportError: No module named arcpy
			好久没写Python脚本了,今天一运行就报错:未找到名称为 arcpy 的模块(ImportError: No module named arcpy). 多半是环境变量出问题了,Python最令人讨厌 ... 
- 给你一个能生成1到5随机数的函数,用它写一个函数生成1到7的随机数。 (即,使用函数rand5()来实现函数rand7())
			给你一个能生成1到5随机数的函数,用它写一个函数生成1到7的随机数. (即,使用函数rand5()来实现函数rand7()). 解答 rand5可以随机生成1,2,3,4,5:rand7可以随机生成1 ... 
- javaweb笔记分享
			Lesson 1 一.eclipse工具的使用 1. java代码的位置 1) 选择工作空间 workspace 选择一个文件夹存放程序(代码) 不要用中文和空格 2) 新建一个java 工程(Pr ... 
- vue 目录结构与文件配置说明
			目录结构与文件配置说明 首先对目录结构进行说明, 1.build目录,主要利用webpack与node插件启动一些相关服务的js文件 2.config目录主要是针对开发环境,生产环境,测试环境的配置信 ... 
- EXCEPTION-TOMCAT
			CreateTime--2016年10月24日16:22:12Author:Marydon声明:异常类文章主要是记录了我遇到的异常信息及解决方案,解决方案大部分都是百度解决的,(这里只是针对我遇到 ... 
- 【VMware】宿主机连接wifi,虚拟机中的Linux系统配置连接wifi
			环境描述 宿主机:Windows 10 64bit 虚拟机:Centos 第一步:虚拟机设置 选择连接方式为NAT 第二步:设置宿主机的wifi 控制面板>>网络和Internet> ... 
- python之函数用法__setattr__
			# -*- coding: utf-8 -*- #python 27 #xiaodeng #python之函数用法__setattr__ #http://www.cnblogs.com/hongfei ... 
- mysql的常用函数、流程控制
			case when用法: END END if用法 IF(expr1,expr2,expr3) #表达式expr1为真则返回expr2否则为expr3 , , ) #结果: 1 ifnull用法: I ... 
- 微信小程序-自定义底部导航
			代码地址如下:http://www.demodashi.com/demo/14258.html 一.前期准备工作 软件环境:微信开发者工具 官方下载地址:https://mp.weixin.qq.co ... 
- 简单安装MongoDB
			前言 首先说明一下环境,以免环境的不同造成不必要的影响 本次采用centos6.8版本linux系统 [root@dev1 ~]# cat /etc/redhat-release CentOS rel ... 
