AI智能
改变未来

Android动画(七)实战使用

今天给大家带来动画的实战练习,今天是一年一度的高考,祝各位考生能梦寐以求.

  • 完成效果
  • ListView滑动进入动画
  • **android:animationOrder = \”normal\”** 正序播放效果:
  • **android:animationOrder=\”reverse\”** 倒序播放效果
  • **android:animationOrder=\”random\”** 随机效果
  • 动态代码实现
  • 菜单弹框效果:
  • 完成效果


    今天给大家带来2个效果:

    • 一个是ListView的滑动进入
    • 另一个是右下角的点击弹框效果

    ListView滑动进入动画

    第一步,先在布局中使用LIstView,在res/layout_animation创建文件,并使用android:layoutAnimation=\”@anim/layout_animation\”引用到ListView中

    第二步:layout_animation文件根目录为layoutAnimation

    <?xml version=\"1.0\" encoding=\"utf-8\"?><layoutAnimation xmlns:android=\"http://schemas.android.com/apk/res/android\"android:delay=\"0.3\"android:animationOrder=\"normal\"android:animation=\"@anim/set_buttonanimator_activity\"></layoutAnimation>
    • android:delay= “float” 可以理解为每个个item相隔滑动的时间
    • android:animationOrder= “normal | random | reverse”normal 按顺序弹出
    • random 随机弹出
    • reverse 倒序弹出
  • android:animation = “@anim/XXX” 弹出的动画
  • 第三步: 在anim下创建set_buttonanimator_activity.xml设置向右滑动,并且透明度由0-1,时长为1s

    <set xmlns:android=\"http://schemas.android.com/apk/res/android\" android:duration=\"1000\" ><translate android:fromXDelta=\"-50%p\" android:toXDelta=\"0\"/><alpha android:fromAlpha=\"0.0\" android:toAlpha=\"1.0\"/></set>

    第四步:在布局中使用ListView

    ListView listView = findViewById(R.id.listview);ArrayList<String> list = new ArrayList<>();list.add(\"测试数据1\");list.add(\"测试数据2\");list.add(\"测试数据3\");list.add(\"测试数据4\");list.add(\"测试数据5\");list.add(\"测试数据6\");这里使用的布局是android中自带的ArrayAdapter<String> stringArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_expandable_list_item_1, list);listView.setAdapter(stringArrayAdapter);
    <layoutAnimation xmlns:android=\"http://schemas.android.com/apk/res/android\"android:delay=\"0.3\"android:animationOrder=\"normal\"android:animation=\"@anim/set_buttonanimator_activity\"></layoutAnimation>

    android:animationOrder = “normal” 正序播放效果:

    android:animationOrder=“reverse” 倒序播放效果

    android:animationOrder=“random” 随机效果

    动态代码实现

    //代码设置通过加载XML动画设置文件来创建一个Animation对象;Animation animation= AnimationUtils.loadAnimation(this,R.anim.set_buttonanimator_activity);   //得到一个LayoutAnimationController对象;LayoutAnimationController controller = new LayoutAnimationController(animation);   //设置控件显示的顺序;controller.setOrder(LayoutAnimationController.ORDER_RANDOM);   //设置控件显示间隔时间;controller.setDelay(0.3f);   //为ListView设置LayoutAnimationController属性;listView.setLayoutAnimation(controller);listView.startLayoutAnimation();
    • ORDER_NORMAL = 0 正常顺序
    • ORDER_REVERSE = 1倒序
    • ORDER_RANDOM = 2 随机顺序

    大家可以从源码中找到注释来看是什么意思;

    菜单弹框效果:


    滑动的效果很简单,alpha从0 – 1 , scale 从0 – 1,最复杂的就是找到每个控件对应的X,和Y的位置,接下来给大家简单分析一下.

    从这张图中可以简单地看出,想要求得X和Y的距离,就必须获得半径r,和夹角a,半径默认为600,那么每个a的夹角是多少呢?从黄色控件和,紫色控件来看,他们的夹角为直角,就是90°,那么他们吧5个控件分为了4等份,那么每一份的夹角就是90 / 4 = 22.5°,那么蓝色与紫色的夹角就是22.5 * 2 = 45°,红色与紫色就是 22.5 * 3 = 67.5黄色与紫色就是22.5 * 4 = 90°.然后通过数学公式:

    X = r * sin(a)
    Y = r * cos(a)

    即可获得X和Y的坐标
    想必大家知道Java提供了一个Math类:

    /*** Returns the trigonometric sine of an angle.  Special cases:* <ul><li>If the argument is NaN or an infinity, then the* result is NaN.* <li>If the argument is zero, then the result is a zero with the* same sign as the argument.</ul>** <p>The computed result must be within 1 ulp of the exact result.* Results must be semi-monotonic.** @param   a   an angle, in radians.* @return  the sine of the argument.*/求正弦值@CriticalNativepublic static native double sin(double a);/*** Returns the trigonometric cosine of an angle. Special cases:* <ul><li>If the argument is NaN or an infinity, then the* result is NaN.</ul>** <p>The computed result must be within 1 ulp of the exact result.* Results must be semi-monotonic.** @param   a   an angle, in radians.* @return  the cosine of the argument.*/求余弦值@CriticalNativepublic static native double cos(double a);/*** Returns the trigonometric tangent of an angle.  Special cases:* <ul><li>If the argument is NaN or an infinity, then the result* is NaN.* <li>If the argument is zero, then the result is a zero with the* same sign as the argument.</ul>** <p>The computed result must be within 1 ulp of the exact result.* Results must be semi-monotonic.** @param   a   an angle, in radians.* @return  the tangent of the argument.*/求正切值@CriticalNativepublic static native double tan(double a);

    注意:这里的参数不是填的角度,而是填的角度对应的弧度

    接下来看看什么是弧度:


    简单的来说,夹角a对面的就是a的弧度;

    使用Math类中的toRadians(flaot)方法,参数填的是角度

    /*** Converts an angle measured in degrees to an approximately* equivalent angle measured in radians.  The conversion from* degrees to radians is generally inexact.** @param   angdeg   an angle, in degrees* @return  the measurement of the angle {@code angdeg}*          in radians.* @since   1.2*/public static double toRadians(double angdeg) {return angdeg / 180.0 * PI;}

    这样就可以初略的得出:

    X = r * sin (Math.toRadians(22))
    Y = r * cos (Math.toRadians(22))

    接下来直接上代码了:

    <?xml version=\"1.0\" encoding=\"utf-8\"?><RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"xmlns:app=\"http://schemas.android.com/apk/res-auto\"xmlns:tools=\"http://schemas.android.com/tools\"android:layout_width=\"match_parent\"android:layout_height=\"match_parent\"tools:context=\".ButtonAnimatorActivity\"><Buttonandroid:id=\"@+id/openButton\"style=\"@style/OpenButton\"android:background=\"@color/colorPrimary\"android:layout_margin=\"30dp\"/><Buttonandroid:id=\"@+id/bt1\"style=\"@style/OpenButton\"android:background=\"#ff00ff\"android:visibility=\"gone\"android:layout_margin=\"30dp\"/><Buttonandroid:id=\"@+id/bt2\"style=\"@style/OpenButton\"android:background=\"#00ffff\"android:visibility=\"gone\"android:layout_margin=\"30dp\"/><Buttonandroid:id=\"@+id/bt3\"style=\"@style/OpenButton\"android:background=\"#0048FF\"android:visibility=\"gone\"android:layout_margin=\"30dp\"/><Buttonandroid:id=\"@+id/bt4\"style=\"@style/OpenButton\"android:background=\"#FF003B\"android:layout_margin=\"30dp\"android:visibility=\"gone\"/><Buttonandroid:id=\"@+id/bt5\"style=\"@style/OpenButton\"android:visibility=\"gone\"android:background=\"#FFDD00\"android:layout_margin=\"30dp\"/></RelativeLayout>

    将共同的代码抽取到values/styles下,然后在引用,可以减少写很多重复代码;

    <style name=\"OpenButton\" ><item name=\"android:layout_width\">50dp</item><item name=\"android:layout_height\">50dp</item><item name=\"android:layout_alignParentEnd\">true</item><item name=\"android:layout_alignParentBottom\">true</item></style>

    接下来获取控件Id,并且设置点击事件:

    private Button openButton;private Button bt1;private Button bt2;private Button bt3;private Button bt4;private Button bt5;openButton = findViewById(R.id.openButton);bt1 = findViewById(R.id.bt1);bt2 = findViewById(R.id.bt2);bt3 = findViewById(R.id.bt3);bt4 = findViewById(R.id.bt4);bt5 = findViewById(R.id.bt5);openButton.setOnClickListener(this);bt1.setOnClickListener(this);bt2.setOnClickListener(this);bt3.setOnClickListener(this);bt4.setOnClickListener(this);bt5.setOnClickListener(this);
    设置此变量是为了设置点击按钮出现不同的效果,因为这里需要打开和关闭Boolean buttonType = false;@Overridepublic void onClick(View v) {if (v.getId() == R.id.openButton) {if (!buttonType) {buttonType = true;打开bt1 - bt5setOpenButton(bt1,0,5,600);setOpenButton(bt2,1,5,600);setOpenButton(bt3,2,5,600);setOpenButton(bt4,3,5,600);setOpenButton(bt5,4,5,600);}else{buttonType = false;关闭bt1 - bt5setCloseButton(bt1,0,5,600);setCloseButton(bt2,1,5,600);setCloseButton(bt3,2,5,600);setCloseButton(bt4,3,5,600);setCloseButton(bt5,4,5,600);}}else{Toast.makeText(this, \"点击了\"+v.getId(), Toast.LENGTH_SHORT).show();}}

    打开按钮方法:

    /**** @param button    控件对象* @param index     当前按钮下标* @param number    按钮总个数* @param radio     圆的半径*/private void setOpenButton(Button button, int index, int number, int radio) {button.setVisibility(View.VISIBLE);double degree = Math.toRadians(90)/(number - 1) * index;Log.i(\"setOpenButton\",degree+\"\");这里需要注意,获取到结果之后要加负号(-),因为正数是往右下角弹出的,咋们现在需要向左上角弹出.float x = (float) -(radio * Math.sin(degree));float y = (float) -(radio * Math.cos(degree));Log.i(\"szjdegree\"+index,x+\"\\t\\t\"+y);AnimatorSet animatorSet = new AnimatorSet();animatorSet.playTogether(ObjectAnimator.ofFloat(button,\"translationX\",0,x),ObjectAnimator.ofFloat(button,\"translationY\",0,y),ObjectAnimator.ofFloat(button,\"alpha\",0,1),ObjectAnimator.ofFloat(button,\"scaleX\",0,1),ObjectAnimator.ofFloat(button,\"scaleY\",0,1));animatorSet.setDuration(500);animatorSet.start();}

    按钮的关闭方法:

    private void setCloseButton(final Button button, int index, int number, int radio) {double degree =   Math.toRadians(90) / (number - 1) * index;int x = (int) - (radio * Math.sin(degree));int y = (int) - (radio * Math.cos(degree));Log.i(\"setCloseButton\",degree+\"\\n\");Log.i(\"setXXX\"+ index,x+\"\\t\\t\"+y);AnimatorSet animatorSet = new AnimatorSet();animatorSet.playTogether(ObjectAnimator.ofFloat(button,\"translationX\",x , 0),ObjectAnimator.ofFloat(button,\"translationY\",y , 0),ObjectAnimator.ofFloat(button,\"alpha\",1 , 0),ObjectAnimator.ofFloat(button,\"scaleX\",1 , 0),ObjectAnimator.ofFloat(button,\"scaleY\",1 , 0));animatorSet.setDuration(500);animatorSet.start();new Handler().postDelayed(new Runnable() {@Overridepublic void run() {button.setVisibility(View.INVISIBLE);}},500);}

    按钮的打开和关闭都是一样的,只是有一点不同:

    • 打开是从0 – X && 0 – Y
    • 关闭时从 X – 0 &* Y – 0

    要有细心地朋友可能发现在关闭的时候还多了一个方法:

    new Handler().postDelayed(new Runnable() {@Overridepublic void run() {button.setVisibility(View.INVISIBLE);}},500);

    为什么要加这个东西呢?咋们先看看不加这个东西的效果:

    为什么会出现这种情况呢?因为在第二次缩放控件的时候,他只是回到了绿色控件的地方,并且透明度(alpha)由1变到了0,只是他的状态不存在了,可是他的值还有,所以他不显示的时候需要吧他隐藏掉,
    我这里用到的是handler的延时操作:

    new Handler().postDelayed(new Runnable() {@Overridepublic void run() {button.setVisibility(View.INVISIBLE);}},500);

    因为代码执行的很快很快,所以不用担心有什么问题,如果觉得不保险,也可以对animatorSet监听,当动画结束的时候会响应onAnimationEnd()事件

    animatorSet.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {button.setVisibility(View.INVISIBLE);}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}});

    菜单点击效果参考链接:

    启舰.
    ListView滑动效果参考文档:: 启舰.

    Git地址链接: langyangyang.

    请各位大佬留下宝贵的建议.

    赞(0) 打赏
    未经允许不得转载:爱站程序员基地 » Android动画(七)实战使用