Androd自己定义控件(三)飞翔的小火箭
在前面的自己定义控件概述中已经跟大家分享了Android开发其中自己定义控件的种类。
今天跟大家分享一个非主流的组合控件。 
我们在开发其中,难免须要在不同的场合中反复使用一些控件的组合。而Java的最高目标呢。是消灭全部反复代码。这个时候怎么办呢?办法之中的一个就是创建一个囊括逻辑和布局的视图,以便能够反复使用而不用在不同的场合中写反复的代码。代码复用的同一时候我们还把逻辑包装到了控件内部,做到更好的解耦。
比方我们App页面中的顶栏等等。
今天呢,跟大家分享一个我前一阵子在项目中遇到的实例。
先看下效果图:
需求:
- 该控件能够左右滑动。
 - 底部积分是一个等差数列。能够自己定义。积分初始为半透明,小红旗下方显示设定的最大值。
小火箭会飞到当前用户相应的积分位置,用户得到的积分在小火箭动画之后会显示为白色,同一时候当前积分位置出现一条标识线。
 - 动画開始的时候小火箭会从0開始移动。直到当前积分位置,在移动过程中小火箭会有一个喷射火焰的效果。
 - 背景会随着火箭的移动而移动,当动画结束的时候,保证小火箭在屏幕中心。
 
实现方式:
自己写一个类继承HorizontalScrollView,HorizontalScrollView会帮我们处理左右滑动的事件,否则还要重写ontouchEvent自己处理滑动。然后载入一个布局文件,给小火箭加一个帧动画和位移属性动画,实现小火箭的移动和喷火动画。
同一时候自己定义一个动画。来处理控件本身的滑动。
须要的技能点:
1.Android的view动画和属性动画,以及简单的自己定义动画。 
2.view的绘制流程,详情參照Androd自己定义控件(一)概述。 
3.Activity中view的载入机制。 
4.Android中dp。px等单位的概念。
5.用代码创建控件。 
6.LayoutParams的用法。
详细实现:
初始化,在这里我们让一个參数的构造方法调用两个參数的构造方法,两个參数的构造方法调用三个參数的构造方法。把初始化的方法放到三个參数的构造方法其中。
在初始化方法中载入布局文件。
public PointView(Context context) {
        this(context, null);
    }
    public PointView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public PointView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        LayoutInflater.from(context).inflate(R.layout.point_view, this);
        initView();
        this.context = context;
        bottomLeftMargin = UIUtil.dip2px(context, 65);
    }
    private void initView() {
        //顶部内容区域
        content = (FrameLayout) findViewById(R.id.point_content);
        rocket = (ImageView) findViewById(R.id.point_rocket);
        //底部标注
        one = (TextView) findViewById(R.id.point_one);
        two = (TextView) findViewById(R.id.point_two);
        three = (TextView) findViewById(R.id.point_three);
        four = (TextView) findViewById(R.id.point_four);
        five = (TextView) findViewById(R.id.point_five);
        six = (TextView) findViewById(R.id.point_six);
        seven = (TextView) findViewById(R.id.point_seven);
        pointMax = (TextView) findViewById(R.id.point_max);
        mark = (LinearLayout) findViewById(R.id.point_mark);
        bottom = (FrameLayout) findViewById(R.id.point_bottom);
    }
布局文件
<?xml version="1.0" encoding="utf-8"?>
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:scrollbars="none">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@mipmap/point_view_bg"
        android:orientation="vertical">
        <!-- 内容区域 -->
        <FrameLayout
            android:id="@+id/point_content"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
            <ImageView
                android:id="@+id/point_rocket"
                android:layout_width="80dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="15dp"
                android:layout_marginTop="85dp"
                android:src="@mipmap/rocket_four" />
        </FrameLayout>
        <!-- 底部标注 -->
        <FrameLayout
            android:id="@+id/point_bottom"
            android:layout_width="match_parent"
            android:layout_height="57dp">
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="horizontal">
                <TextView
                    android:layout_width="30dp"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="10dp"
                    android:layout_marginTop="7dp"
                    android:text="积分"
                    android:textColor="#fff"
                    android:textSize="14sp" />
                <LinearLayout
                    android:id="@+id/point_mark"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1">
                    <LinearLayout
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:orientation="vertical">
                        <LinearLayout
                            android:layout_width="50dp"
                            android:layout_height="match_parent"
                            android:gravity="center_horizontal"
                            android:orientation="vertical">
                            <ImageView
                                android:layout_width="1px"
                                android:layout_height="5dp"
                                android:background="@color/light_red" />
                            <TextView
                                android:id="@+id/point_one"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_marginTop="3dp"
                                android:text="0"
                                android:textColor="@color/white"
                                android:textSize="12sp" />
                        </LinearLayout>
                    </LinearLayout>
                    <LinearLayout
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:orientation="vertical">
                        <LinearLayout
                            android:layout_width="50dp"
                            android:layout_height="match_parent"
                            android:gravity="center_horizontal"
                            android:orientation="vertical">
                            <ImageView
                                android:layout_width="1px"
                                android:layout_height="5dp"
                                android:background="@color/light_red" />
                            <TextView
                                android:id="@+id/point_two"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_marginTop="3dp"
                                android:text="300"
                                android:textColor="@color/zhuce"
                                android:textSize="12sp" />
                        </LinearLayout>
                    </LinearLayout>
                    <LinearLayout
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:orientation="vertical">
                        <LinearLayout
                            android:layout_width="50dp"
                            android:layout_height="match_parent"
                            android:gravity="center_horizontal"
                            android:orientation="vertical">
                            <ImageView
                                android:layout_width="1px"
                                android:layout_height="5dp"
                                android:background="@color/light_red" />
                            <TextView
                                android:id="@+id/point_three"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_marginTop="3dp"
                                android:text="600"
                                android:textColor="@color/zhuce"
                                android:textSize="12sp" />
                        </LinearLayout>
                    </LinearLayout>
                    <LinearLayout
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:orientation="vertical">
                        <LinearLayout
                            android:layout_width="50dp"
                            android:layout_height="match_parent"
                            android:gravity="center_horizontal"
                            android:orientation="vertical">
                            <ImageView
                                android:layout_width="1px"
                                android:layout_height="5dp"
                                android:background="@color/light_red" />
                            <TextView
                                android:id="@+id/point_four"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_marginTop="3dp"
                                android:text="900"
                                android:textColor="@color/zhuce"
                                android:textSize="12sp" />
                        </LinearLayout>
                    </LinearLayout>
                    <LinearLayout
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:orientation="vertical">
                        <LinearLayout
                            android:layout_width="50dp"
                            android:layout_height="match_parent"
                            android:gravity="center_horizontal"
                            android:orientation="vertical">
                            <ImageView
                                android:layout_width="1px"
                                android:layout_height="5dp"
                                android:background="@color/light_red" />
                            <TextView
                                android:id="@+id/point_five"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_marginTop="3dp"
                                android:text="1200"
                                android:textColor="@color/zhuce"
                                android:textSize="12sp" />
                        </LinearLayout>
                    </LinearLayout>
                    <LinearLayout
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:orientation="vertical">
                        <LinearLayout
                            android:layout_width="50dp"
                            android:layout_height="match_parent"
                            android:gravity="center_horizontal"
                            android:orientation="vertical">
                            <ImageView
                                android:layout_width="1px"
                                android:layout_height="5dp"
                                android:background="@color/light_red" />
                            <TextView
                                android:id="@+id/point_six"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_marginTop="3dp"
                                android:text="1500"
                                android:textColor="@color/zhuce"
                                android:textSize="12sp" />
                        </LinearLayout>
                    </LinearLayout>
                    <LinearLayout
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:orientation="vertical">
                        <LinearLayout
                            android:layout_width="50dp"
                            android:layout_height="match_parent"
                            android:gravity="center_horizontal"
                            android:orientation="vertical">
                            <ImageView
                                android:layout_width="1px"
                                android:layout_height="5dp"
                                android:background="@color/light_red" />
                            <TextView
                                android:id="@+id/point_seven"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_marginTop="3dp"
                                android:text="1800"
                                android:textColor="@color/zhuce"
                                android:textSize="12sp" />
                        </LinearLayout>
                    </LinearLayout>
                </LinearLayout>
                <TextView
                    android:id="@+id/point_max"
                    android:layout_width="58dp"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="10dp"
                    android:layout_marginTop="7dp"
                    android:gravity="center"
                    android:textColor="@color/zhuce"
                    android:textSize="12sp" />
                <View
                    android:layout_width="33dp"
                    android:layout_height="match_parent" />
            </LinearLayout>
        </FrameLayout>
    </LinearLayout>
</HorizontalScrollView>
然后在onlayout方法中拿到我们须要的底部标注的长度,用来计算小火箭和view动画的位移。
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        markLength = mark.getMeasuredWidth();
//        L.e(TAG, "markLength---" + markLength);
    }
设置显示标注线
/**
     * 设置当前分数
     *
     * @param point
     */
    public void setCurrentPoint(int point) {
        int location;
        if (point < MAX_POINT) {
            location = (int) ((point / MAX_POINT) * markLength + bottomLeftMargin);//算出当前分数显示位置的偏移量
        } else {
            location = markLength + bottomLeftMargin + UIUtil.dip2px(context, 12);
        }
        //标注当前位置,
        ImageView line = new ImageView(context);
        line.setImageDrawable(getResources().getDrawable(R.color.point_line));
        bottom.addView(line);
        LayoutParams linePa = (LayoutParams) line.getLayoutParams();
        linePa.leftMargin = location;
        linePa.width = UIUtil.dip2px(context, 1);
        linePa.height = UIUtil.dip2px(context, 58);
        line.setLayoutParams(linePa);
//        L.e(TAG, "location---" + location + ";bottomLeftMargin---" + bottomLeftMargin);
    }
火箭的动画
//火箭平移动画
        ObjectAnimator rocketAni = ObjectAnimator.ofFloat(rocket, "translationX", rocketX);
        DecelerateInterpolator interpolator = new DecelerateInterpolator();
        rocketAni.setInterpolator(interpolator);
        rocketAni.setDuration(DEFAULT_DURATION);
        rocketAni.start();
        //火箭切换动画
        rocket.setImageResource(R.drawable.rocket_frame);
        final AnimationDrawable animationDrawable = (AnimationDrawable) rocket.getDrawable();
        animationDrawable.start();
        rocketAni.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                //停止帧动画
                animationDrawable.stop();
                rocket.setImageResource(R.mipmap.rocket_three);
                //设置当前积分标注线
                setCurrentPoint(point);
                //设置已经到达积分为白色
                setMarkColor(point, 300);
            }
        });
由于scroller自带的滚动插值器与火箭动画插值器不同步,所以使用自己定义动画实现控件的平滑滚动
/**
     * 自己定义动画,控制scrollview滚动
     */
    public class ViewAnimation extends Animation {
        private int viewX;
        public ViewAnimation(int viewX) {
            this.viewX = viewX;
        }
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            super.applyTransformation(interpolatedTime, t);
            smoothScrollTo((int) (viewX * interpolatedTime), 0);
        }
    }
    //view滚动动画
        /**
         * scroller自带的滚动插值器与火箭动画插值器不同步,所以使用自己定义动画实现平滑滚动
         */
        ViewAnimation viewAnimation = new ViewAnimation(finalViewX);
        viewAnimation.setDuration(DEFAULT_DURATION);
        viewAnimation.setInterpolator(interpolator);
        this.setAnimation(viewAnimation);
        viewAnimation.start();
调用
@Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        mPoinView.setMaxPoint(2500);
        mPoinView.startAni(600);
    }
这里我们在onWindowFocusChanged回调中调用。保证在控件载入完毕之后再设置參数。
到这里这个控件就基本完毕了。事实上还有非常多能够优化的地方,比方把一些属性抽离出来,写成自己定义属性,还有下标依据传入数组动态生成等等,有兴趣的朋友能够交流一下。
Androd自己定义控件(三)飞翔的小火箭的更多相关文章
- Android自己定义控件系列三:自己定义开关button(二)
		
接上一篇自己定义开关button(一)的内容继续.上一次实现了一个开关button的基本功能.即自己定义了一个控件.开关button,实现了点击切换开关状态的功能.今天我们想在此基础之上.进一步实现触 ...
 - Android自己定义控件(状态提示图表)
		
[工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处.尊重分享成果] 1 背景 前面分析那么多系统源代码了.也该暂停下来歇息一下,趁昨晚闲着看见一个有意思的需求就操 ...
 - Android自己定义控件系列五:自己定义绚丽水波纹效果
		
尊重原创!转载请注明出处:http://blog.csdn.net/cyp331203/article/details/41114551 今天我们来利用Android自己定义控件实现一个比較有趣的效果 ...
 - Android自己定义控件系列二:自己定义开关button(一)
		
这一次我们将会实现一个完整纯粹的自己定义控件,而不是像之前的组合控件一样.拿系统的控件来实现.计划分为三部分:自己定义控件的基本部分,自己定义控件的触摸事件的处理和自己定义控件的自己定义属性: 以下就 ...
 - Android自己定义控件:进度条的四种实现方式
		
前三种实现方式代码出自: http://stormzhang.com/openandroid/2013/11/15/android-custom-loading/ (源代码下载)http://down ...
 - 【Asp.net之旅】--因自己定义控件注冊而引发的思考
		
前言 近期在开发远洋的SOA系统平台,开发使用的是.NET平台.对于Asp.net并不困难,但该系统的开发并非全然依靠Asp.net.而是自身封装好的框架.这套框架是远洋地产购买的微软的开发平台,项目 ...
 - 自己定义控件事实上非常easy1/6
		
尊重原创转载请注明:From AigeStudio(http://blog.csdn.net/aigestudio)Power by Aige 侵权必究! 炮兵镇楼 上一节我们粗略地讲了下怎样去实现我 ...
 - android 自己定义控件
		
Android自己定义View实现非常easy 继承View,重写构造函数.onDraw.(onMeasure)等函数. 假设自己定义的View须要有自己定义的属性.须要在values下建立attrs ...
 - Android  实现形态各异的双向側滑菜单 自己定义控件来袭
		
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39670935.本文出自:[张鸿洋的博客] 1.概述 关于自己定义控件側滑已经写了 ...
 
随机推荐
- 基于ASP.Net Core开发一套通用后台框架记录-(项目的搭建)
			
写在前面 本系列博客是本人在学习的过程中搭建学习的记录,如果对你有所帮助那再好不过.如果您有发现错误,请告知我,我会第一时间修改. 前期我不会公开源码,我想是一点点敲代码,不然复制.粘贴那就没意思了. ...
 - HTML--使用mailto在网页中链接Email地址
			
<a>标签还有一个作用是可以链接Email地址,使用mailto能让访问者便捷向网站管理者发送电子邮件.我们还可以利用mailto做许多其它事情.下面一一进行讲解,请看详细图示: 注意:如 ...
 - HTML--使用下拉列表框,节省空间
			
下拉列表在网页中也常会用到,它可以有效的节省网页空间.既可以单选.又可以多选.如下代码: 讲解: 1.value: 2.selected="selected": 设置selecte ...
 - ORA-01012:not logged on的解决办法
			
conn / as sysdba 报错ORA-01012: not logged on 发生原因:关闭数据库是shutdown 后面没有接关闭参数中的任何一个. nomal ————- —-所有连接都 ...
 - BZOJ 2946 SA/SAM
			
思路: 1. 二分+后缀数组 2.SAM //By SiriusRen #include <cstdio> #include <cstring> #include <al ...
 - Hadoop Hive概念学习系列之hive里的桶(十一)
			
不多说,直接上干货! Hive还可以把表或分区,组织成桶.将表或分区组织成桶有以下几个目的: 第一个目的是为看取样更高效,因为在处理大规模的数据集时,在开发.测试阶段将所有的数据全部处理一遍可能不太 ...
 - 11、scala函数式编程
			
1.将函数赋值给变量 2.匿名函数 3.高阶函数 4.高阶函数的类型推断 5.Scala的常用高级函数 6.闭包 7.SAM转换 8.Currying函数 9.return 1.将函数赋值给变量 Sc ...
 - WebAPI PUT,DELETE请求404
 - Centos6.7安装Cacti教程
			
Centos6.7安装Cacti教程# link:http://docs.cacti.net/plugins/ blog地址:http://www.cnblogs.com/caoguo 一.基本环境安 ...
 - js post一个对象 在C#中怎么接收? 未解决
			
这个在C#中怎么接收?