Android属性动画——实现灵动菜单效果

前段时间,我学习了自定义View,基本能够绘制一些比较好看的控件,那么今天开始,我将会学习属性动画。前面我也简单的看过属性动画的概念,然后也是看了一下效果,了解了一些基本概念,比如Animator、ObjectAnimator、插值器等等。为此我还特意写了博客Android技术进阶的要素——Android属性动画,但是没有一个项目去巩固,也一直耿耿于怀,今天终于可以开始写这方面的程序了,好了,讲了这么多的废话,下面开始看看今天的内容,我是通过demo来了解属性动画的。先看你效果:

这里写图片描述

这个就是展开后的效果了,由于不是动态图,所以看不到全部效果,我简单的描述一下,当点击中间的“”+“的时候,会从“+”处灵动的弹出三个按钮,这三个按钮的出现过程中,也带有动画效果,同样的,关闭也是如此,同样的,这三个按钮也同样的注册了点击事件。

接下来,我们开始编码,因为这个菜单是以一个整体的形式展现出来的,所以,我这里是把这个控件当成一个ViewGroup来实现,

新建一个类,名字叫MMenu,继承自RelativeLayout,并且实现了点击事件的接口,下面看看我们这一次所用到的变量:

    private ImageView center,home,call,hyperlink;

    private List<ImageView> oViews;

    private boolean mFlag=true;

    private float mHiddenViewMeasuredHeight;

不多,首先是有四个图片控件、然后是一个list集合,用于装载Imageview,下面的一个标志,是用来区分打开或者关闭菜单栏,再一个就是动画的位移长度。

下面开始初始化操作:

    private void initView(Context context) {

        LayoutInflater.from(context).inflate(R.layout.menu_layout, this);
        center=(ImageView) findViewById(R.id.center);
        call=(ImageView) findViewById(R.id.call);
        home=(ImageView) findViewById(R.id.home);
        hyperlink=(ImageView) findViewById(R.id.hyperlink);

        //将四个Imageview放在集合里,方便管理
        oViews=new ArrayList<ImageView>();
        oViews.add(center);
        oViews.add(call);
        oViews.add(home);
        oViews.add(hyperlink);

        center.setOnClickListener(this);
        call.setOnClickListener(this);
        home.setOnClickListener(this);
        hyperlink.setOnClickListener(this);
    }

这里加载了布局文件、然后引入了控件、设置了点击事件等等。接下来在onSizeChanged方法里面给位移的大小赋值,代码如下:

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mHiddenViewMeasuredHeight = (int) (w*1/12);
        Anim(mHiddenViewMeasuredHeight,-mHiddenViewMeasuredHeight ,0.5f, 1f, 0f, 90f);

    }

这里我们一开始设置对菜单进行关闭。下面开始主要代码,对控件的动画效果进行一个操作,代码如下:


    private void Anim(float mHiddenViewMeasuredHeightBegin,float mHiddenViewMeasuredHeightyClose,float x,float y,float anglex,float angley){

        //设置动画。用于弹出和收回
        ObjectAnimator animator0=ObjectAnimator.ofFloat(oViews.get(0), "alpha", x,y);

        ObjectAnimator animator1=ObjectAnimator.ofFloat(oViews.get(1), "translationX",mHiddenViewMeasuredHeightBegin);

        ObjectAnimator animator2=ObjectAnimator.ofFloat(oViews.get(2), "translationY",mHiddenViewMeasuredHeightBegin);

        ObjectAnimator animator3=ObjectAnimator.ofFloat(oViews.get(3), "translationX",mHiddenViewMeasuredHeightyClose);



        //设置动画,用于旋转效果
        ObjectAnimator animator4=ObjectAnimator.ofFloat(oViews.get(0), "rotation", anglex,120f,angley);

        ObjectAnimator animator5=ObjectAnimator.ofFloat(oViews.get(1), "rotationX", anglex,120f,angley);

        ObjectAnimator animator6=ObjectAnimator.ofFloat(oViews.get(2), "rotationY", anglex,120f,angley);

        ObjectAnimator animator7=ObjectAnimator.ofFloat(oViews.get(3), "rotationX", anglex,120f,angley);

        AnimatorSet set = new AnimatorSet();
        set.setDuration(500);
        set.setInterpolator(new OvershootInterpolator());
        set.playTogether(animator0,animator1,animator2,animator3,animator4,animator5,animator6,animator7);
        set.start();


    }

注释也是比较详细,这里定义个多个控件属性,并且还用到了集合容器,整个的动画效果就是在这里实现的,对于新手而言,这里面的效果很微妙,所以要自己多运行细细体会。

然后就是对面暴露一个点击事件,用于事件的回调,

    //设置事件回调
    public void setonMenuClickListener( onMenuClickListener listener){
        this.listener=listener;
    }

这是这个控件的主要代码,接下来我附上所有的代码:

布局文件:

menu_layout.xml


主页面的布局文件,main.xml:

接下来是主界面代码,Main.java

/**
* 小瓶盖 2016年7月14日16:30:36
*
* @author Android属性动画——实现灵动菜单效果
*
*相关博客地址 http://blog.csdn.net/qq_25193681
*/
public class Main extends Activity {

private MMenu menu;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);



    menu=(MMenu) findViewById(R.id.MMenu);
    menu.setonMenuClickListener(new onMenuClickListener() {
        @Override
        public void hyperlink() {
            Toast.makeText(Main.this, "点击了hyperlink", 0).show();
        }
        @Override
        public void Home() {
            Toast.makeText(Main.this, "点击了home", 0).show();
        }
        @Override
        public void Call() {
            Toast.makeText(Main.this, "点击了Call", 0).show();
        }
    });
}

}


MMenu.java

/**
* 小瓶盖 2016年7月14日16:30:36
*
* @author Android属性动画——实现灵动菜单效果
*
*相关博客地址 http://blog.csdn.net/qq_25193681
*/
public class MMenu extends RelativeLayout implements OnClickListener{

private ImageView center,home,call,hyperlink;

private List<ImageView> oViews;

private boolean mFlag=true;

private float mHiddenViewMeasuredHeight;



public MMenu(Context context, AttributeSet attrs) {
    super(context, attrs);
    initView(context);
}

public MMenu(Context context) {
    super(context);
    initView(context);
}

private void initView(Context context) {

    LayoutInflater.from(context).inflate(R.layout.menu_layout, this);
    center=(ImageView) findViewById(R.id.center);
    call=(ImageView) findViewById(R.id.call);
    home=(ImageView) findViewById(R.id.home);
    hyperlink=(ImageView) findViewById(R.id.hyperlink);

    //将四个Imageview放在集合里,方便管理
    oViews=new ArrayList<ImageView>();
    oViews.add(center);
    oViews.add(call);
    oViews.add(home);
    oViews.add(hyperlink);

    center.setOnClickListener(this);
    call.setOnClickListener(this);
    home.setOnClickListener(this);
    hyperlink.setOnClickListener(this);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mHiddenViewMeasuredHeight = (int) (w*1/12);
    Anim(mHiddenViewMeasuredHeight,-mHiddenViewMeasuredHeight ,0.5f, 1f, 0f, 90f);

}

@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.center:
        if (mFlag) {
            Anim(-mHiddenViewMeasuredHeight,mHiddenViewMeasuredHeight, 1f, 0.5f, 90f, 0f);;
            mFlag=false;
        }else {
            Anim(mHiddenViewMeasuredHeight, -mHiddenViewMeasuredHeight,0.5f, 1f, 0f, 90f);
            mFlag=true;
        }
        break;
    case R.id.home:
        if (listener!=null) {
            listener.Home();
        }
        break;
    case R.id.call:
        if (listener!=null) {
            listener.Call();
        }
        break;

    case R.id.hyperlink:
        if (listener!=null) {
            listener.hyperlink();
        }
        break;

    default:
        break;
    }
}


private void Anim(float mHiddenViewMeasuredHeightBegin,float mHiddenViewMeasuredHeightyClose,float x,float y,float anglex,float angley){

    //设置动画。用于弹出和收回
    ObjectAnimator animator0=ObjectAnimator.ofFloat(oViews.get(0), "alpha", x,y);

    ObjectAnimator animator1=ObjectAnimator.ofFloat(oViews.get(1), "translationX",mHiddenViewMeasuredHeightBegin);

    ObjectAnimator animator2=ObjectAnimator.ofFloat(oViews.get(2), "translationY",mHiddenViewMeasuredHeightBegin);

    ObjectAnimator animator3=ObjectAnimator.ofFloat(oViews.get(3), "translationX",mHiddenViewMeasuredHeightyClose);



    //设置动画,用于旋转效果
    ObjectAnimator animator4=ObjectAnimator.ofFloat(oViews.get(0), "rotation", anglex,120f,angley);

    ObjectAnimator animator5=ObjectAnimator.ofFloat(oViews.get(1), "rotationX", anglex,120f,angley);

    ObjectAnimator animator6=ObjectAnimator.ofFloat(oViews.get(2), "rotationY", anglex,120f,angley);

    ObjectAnimator animator7=ObjectAnimator.ofFloat(oViews.get(3), "rotationX", anglex,120f,angley);

    AnimatorSet set = new AnimatorSet();
    set.setDuration(500);
    set.setInterpolator(new OvershootInterpolator());
    set.playTogether(animator0,animator1,animator2,animator3,animator4,animator5,animator6,animator7);
    set.start();


}
onMenuClickListener listener;
//设置事件回调
public void setonMenuClickListener( onMenuClickListener listener){
    this.listener=listener;
}

}

还有一个接口,用于实现回调事件:

/**
* 小瓶盖 2016年7月14日16:30:36
*
* @author Android属性动画——实现灵动菜单效果
*
*相关博客地址 http://blog.csdn.net/qq_25193681
*/
public interface onMenuClickListener {
void Home();
void Call();
void hyperlink();
}

“`
所有的代码都在这里了,因为我自己也是刚刚接触,所以博客可能有很多的瑕疵,也请各位同僚批评指出。

最后我贴出源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值