• Androd自己定义控件(三)飞翔的小火箭


    在前面的自己定义控件概述中已经跟大家分享了Android开发其中自己定义控件的种类。

    今天跟大家分享一个非主流的组合控件。
    我们在开发其中,难免须要在不同的场合中反复使用一些控件的组合。而Java的最高目标呢。是消灭全部反复代码。这个时候怎么办呢?办法之中的一个就是创建一个囊括逻辑和布局的视图,以便能够反复使用而不用在不同的场合中写反复的代码。代码复用的同一时候我们还把逻辑包装到了控件内部,做到更好的解耦。

    比方我们App页面中的顶栏等等。


    今天呢,跟大家分享一个我前一阵子在项目中遇到的实例。

    先看下效果图:

    需求:

    1. 该控件能够左右滑动。
    2. 底部积分是一个等差数列。能够自己定义。积分初始为半透明,小红旗下方显示设定的最大值。

      小火箭会飞到当前用户相应的积分位置,用户得到的积分在小火箭动画之后会显示为白色,同一时候当前积分位置出现一条标识线。

    3. 动画開始的时候小火箭会从0開始移动。直到当前积分位置,在移动过程中小火箭会有一个喷射火焰的效果。
    4. 背景会随着火箭的移动而移动,当动画结束的时候,保证小火箭在屏幕中心。

    实现方式:

    自己写一个类继承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回调中调用。保证在控件载入完毕之后再设置參数。

    到这里这个控件就基本完毕了。事实上还有非常多能够优化的地方,比方把一些属性抽离出来,写成自己定义属性,还有下标依据传入数组动态生成等等,有兴趣的朋友能够交流一下。

    源代码地址。

  • 相关阅读:
    如何选择开源许可证?(转)
    gdb的使用(转)
    git的使用
    2017-3-13 leetcode 4 11 15
    2017-3-12 leetcode 167 209 216
    2017-3-11 leetcode 217 219 228
    2017-3-10 leetcode 229 238 268
    1175: 零起点学算法82——find your present
    1174: 零起点学算法81——求整数绝对值
    1173: 零起点学算法80——求实数绝对值
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/7131094.html
Copyright © 2020-2023  润新知