自定义控件笔记1

2018-06-07  本文已影响0人  唐嘉娆

自定义控件:用系统自带控件重新组合或者自定义类继承View或者自定义类继承ViewGroup,实现特定的UI效果。

重点:
a.View和ViewGroup的区别
b.Android中事件的传递
c.View的原理

事例一:优酷菜单


youku1.png

由于这里是以中心为旋转点,所以pivotXValue就是view.getWidth()/2,pivotYValue就是view.getHeight()

class Tools {

    /**
     * 隐藏
     * @param view
     */
    public static void hideView(View view) {

       hideView(view,0);
    }

    /**
     * 显示
     * @param view
     */
    public static void showView(View view) {

       showView(view,0);
    }

    /**
     * 有延迟时间的隐藏
     * @param view
     * @param startOffset
     */
    public static void hideView(View view, int startOffset) {
        /**
         * fromDegrees 从哪个角度 toDegrees 到哪个角度  水平线为x轴
         * pivotXValue  pivotYValue 是相对于x y坐标的位置 控件的左上角的坐标为(0,0) 右下角为(1,1)
         * 由于这里是以中心为旋转点,所以pivotXValue就是view.getWidth()/2,pivotYValue就是view.getHeight()
         *
         */
        RotateAnimation animation = new RotateAnimation(0,180,view.getWidth()/2,view.getHeight());
        //设置动画的速度
        animation.setDuration(500);
        //设置动画结束后停留在改变后的位置
        animation.setFillAfter(true);
        //设置延迟动画时间
        animation.setStartOffset(startOffset);
        view.startAnimation(animation);
    }

    /**
     * 有延迟时间的显示
     * @param view
     * @param startOffset
     */
    public static void showView(View view, int startOffset) {

        RotateAnimation animation = new RotateAnimation(180,360,view.getWidth()/2,view.getHeight());
        //设置动画的速度
        animation.setDuration(500);
        //设置动画结束后停留在改变后的位置
        animation.setFillAfter(true);
        //设置延迟动画时间
        animation.setStartOffset(startOffset);
        view.startAnimation(animation);
    }
}

问题:如果此时隐藏掉所有的菜单,点击一级菜单会出现bug,因为即使这个视图已经旋转过去,但是它的属性还在,所以可以点击。


youku2.png

如果直接修改成以下代码会无效

 /**
     * 有延迟时间的隐藏
     * @param view
     * @param startOffset
     */
    public static void hideView(View view, int startOffset) {
        /**
         * fromDegrees 从哪个角度 toDegrees 到哪个角度  水平线为x轴
         * pivotXValue  pivotYValue 是相对于x y坐标的位置 控件的左上角的坐标为(0,0) 右下角为(1,1)
         * 由于这里是以中心为旋转点,所以pivotXValue就是view.getWidth()/2,pivotYValue就是view.getHeight()
         *
         */
        RotateAnimation animation = new RotateAnimation(0,180,view.getWidth()/2,view.getHeight());
        //设置动画的速度
        animation.setDuration(500);
        //设置动画结束后停留在改变后的位置
        animation.setFillAfter(true);
        //设置延迟动画时间
        animation.setStartOffset(startOffset);
        view.startAnimation(animation);
        view.setEnabled(false);
    }

    /**
     * 有延迟时间的显示
     * @param view
     * @param startOffset
     */
    public static void showView(View view, int startOffset) {

        RotateAnimation animation = new RotateAnimation(180,360,view.getWidth()/2,view.getHeight());
        //设置动画的速度
        animation.setDuration(500);
        //设置动画结束后停留在改变后的位置
        animation.setFillAfter(true);
        //设置延迟动画时间
        animation.setStartOffset(startOffset);
        view.startAnimation(animation);
        view.setEnabled(true);
    }

因为传进来的view是RelativeLayout,而RelativeLayout是继承ViewGroup的,即使其设置了Enabled,也只是对他自身有效,但是他里面的子view依然可以被点击。

解决办法:
1.将View改为ViewGroup,循环出其子View,并且对每个子View设置Enabled。
2.通过属性动画解决

方法1:

/**
     * 有延迟时间的隐藏
     * @param view
     * @param startOffset
     */
    public static void hideView(ViewGroup view, int startOffset) {
        /**
         * fromDegrees 从哪个角度 toDegrees 到哪个角度  水平线为x轴
         * pivotXValue  pivotYValue 是相对于x y坐标的位置 控件的左上角的坐标为(0,0) 右下角为(1,1)
         * 由于这里是以中心为旋转点,所以pivotXValue就是view.getWidth()/2,pivotYValue就是view.getHeight()
         *
         */
        RotateAnimation animation = new RotateAnimation(0,180,view.getWidth()/2,view.getHeight());
        //设置动画的速度
        animation.setDuration(500);
        //设置动画结束后停留在改变后的位置
        animation.setFillAfter(true);
        //设置延迟动画时间
        animation.setStartOffset(startOffset);
        view.startAnimation(animation);
        for (int i = 0;i<view.getChildCount();i++){
            View child = view.getChildAt(i);
            child.setEnabled(false);
        }

    }

    /**
     * 有延迟时间的显示
     * @param view
     * @param startOffset
     */
    public static void showView(ViewGroup view, int startOffset) {

        RotateAnimation animation = new RotateAnimation(180,360,view.getWidth()/2,view.getHeight());
        //设置动画的速度
        animation.setDuration(500);
        //设置动画结束后停留在改变后的位置
        animation.setFillAfter(true);
        //设置延迟动画时间
        animation.setStartOffset(startOffset);
        view.startAnimation(animation);
        for (int i = 0;i<view.getChildCount();i++){
            View child = view.getChildAt(i);
            child.setEnabled(true);
        }

    }

android包含三种动画:View Animation(补间)、Drawable Animation(帧动画)、property Animation(属性动画)

View Animation:
基于View的渐变动画,只改变了View的绘制效果,而实际属性未变,比如动画移动一个按钮的位置,但按钮的实际点击位置未变。在代码中定义动画,可以参考AnimationSet类和Animation子类,而如使用Xml,可以在res/anim/文件夹中定义Xml。(事例一则是View Animation)

Drawable Animation:加载一系列的Drawable资源来创建动画,这种传统动画某种程度上就是创建不同图片序列,顺序播放。在代码中定义使用AnimationDawable类;XMl文件更简单的组成动画帧,在res/drawable文件夹,使用<animation-list>采用<item>来定义不同的帧。

property Animation:动画的对象除了是view对象,还可以是Object对象,动画之后,Object对象的属性值被实实在在的改变。view属性改变,view能自动调用invalidate来刷新。

方法2:

/**
     * 有延迟时间的隐藏
     * @param view
     * @param startOffset
     */
    public static void hideView(ViewGroup view, int startOffset) {


        //使用属性动画
        //第一个参数是作用的对象,第二个参数是要改变的属性名,小写
        //例子 view.setRotation();
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view,"rotation",0,180);
        //设置动画的速度
        objectAnimator.setDuration(500);
        //设置延迟时间
        objectAnimator.setStartDelay(startOffset);
        //设置旋转中心
        view.setPivotX(view.getWidth()/2);
        view.setPivotY(view.getHeight());
        objectAnimator.start();

    }

    /**
     * 有延迟时间的显示
     * @param view
     * @param startOffset
     */
    public static void showView(ViewGroup view, int startOffset) {


        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view,"rotation",180,360);
        //设置动画的速度
        objectAnimator.setDuration(500);
        //设置延迟时间
        objectAnimator.setStartDelay(startOffset);
        //设置旋转中心
        view.setPivotX(view.getWidth()/2);
        view.setPivotY(view.getHeight());
        objectAnimator.start();

    }

更简单的写法:

/**
     * 有延迟时间的隐藏
     * @param view
     * @param startOffset
     */
    public static void hideView(ViewGroup view, int startOffset) {

        OtherFunction(view,startOffset);

    }

    /**
     * 有延迟时间的显示
     * @param view
     * @param startOffset
     */
    public static void showView(ViewGroup view, int startOffset) {

        OtherFunction(view,startOffset);
    }

    private static void OtherFunction(ViewGroup view, int startOffset) {
        //另一种写法
        view.setPivotX(view.getWidth()/2);
        view.setPivotY(view.getHeight());
        view.animate()
                .rotationBy(180)    //旋转角度
                .setDuration(500)
                .setStartDelay(startOffset)
                .start();
    }
上一篇 下一篇

猜你喜欢

热点阅读