【问题标题】:shaking / wobble view animation in androidandroid中的摇晃/摆动视图动画
【发布时间】:2012-03-15 23:09:01
【问题描述】:

我创建了一个如下所示的 anim.xml 文件来像在 android 中晃动 IOS 图标一样晃动 imageview。 但是它并没有为我提供相同的结果。 有没有更好的办法?

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"

    android:fromDegrees="-2"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:toDegrees="2" />

【问题讨论】:

    标签: android android-animation


    【解决方案1】:

    尝试设置android:repeatMode="reverse"。下面的动画对我的 Galaxy Nexus 进行了非常合理的模仿。显然,您可以根据自己的喜好微调参数。

    <?xml version="1.0" encoding="utf-8"?>
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="100"
        android:fromDegrees="-5"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="infinite"
        android:repeatMode="reverse"
        android:toDegrees="5" />
    

    【讨论】:

    • 我是 android 开发新手,我正在使用 Xamarin,你能告诉我如何在点击等任何事件上将此动画应用于图像/按钮。
    • @N.K:它应该像在 Java 中一样工作:通过其资源 ID 加载动画,并通过将其作为参数传递来告诉您的视图启动动画。应该类似于:view.StartAnimation(AnimationUtils.LoadAnimation(Resource.Animation.wobble))。更多详情 herehere
    • 如何添加抖动之间的延迟。例如显示抖动 500 毫秒然后延迟 1000 毫秒然后再重复一次?
    【解决方案2】:

    漂亮的摇晃动画;

    res/anim/shake.xml

    <set xmlns:android="http://schemas.android.com/apk/res/android">
    
        <translate android:duration="150"
            android:fromXDelta="-10%"
            android:repeatCount="5"
            android:repeatMode="reverse"
            android:toXDelta="10%"/>
    </set>
    

    如何使用

    final Animation animShake = AnimationUtils.loadAnimation(this, R.anim.shake);
    btn_done = (Button) findViewById(R.id.btn_act_confirm_done); 
    btn_done.startAnimation(animShake);
    

    如何使用(简单版):

    btn_done.startAnimation(AnimationUtils.loadAnimation(this,R.anim.shake));
    

    【讨论】:

    • android:duration="50" 在我看来不那么波涛汹涌,而且看起来好多了
    【解决方案3】:

    你可以试试这个:

    shake.xml

    <translate xmlns:android="http://schemas.android.com/apk/res/android" 
               android:fromXDelta="0" 
               android:toXDelta="10" 
               android:duration="1000" 
               android:interpolator="@anim/cycle_7" />
    

    cycle_7.xml

    <cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android" 
                       android:cycles="7" />
    

    【讨论】:

    • 嘿,我猜cycle_7.xml 可以替换为&lt;translate .../&gt; 中的android:repeatCount="7" 属性
    【解决方案4】:

    尝试使用这个:

    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <rotate
            android:duration="70"
            android:fromDegrees="-5"
            android:pivotX="50%"
            android:pivotY="50%"
            android:repeatCount="5"
            android:repeatMode="reverse"
            android:interpolator="@android:anim/linear_interpolator"
            android:toDegrees="5" />
        <translate
            android:fromXDelta="-10"
            android:toXDelta="10"
            android:repeatCount="5"
            android:repeatMode="reverse"
            android:interpolator="@android:anim/linear_interpolator"
            android:duration="70" />
    </set>
    

    【讨论】:

      【解决方案5】:

      做出这样的摇晃效果

      首先将anim文件夹中的抖动动画定义为shake.xml

      <?xml version="1.0" encoding="utf-8"?>
      <set xmlns:android="http://schemas.android.com/apk/res/android">
          <rotate
              android:duration="70"
              android:fromDegrees="-5"
              android:interpolator="@android:anim/linear_interpolator"
              android:pivotX="50%"
              android:pivotY="50%"
              android:repeatCount="5"
              android:repeatMode="reverse"
              android:toDegrees="5" />
          <translate
              android:duration="70"
              android:fromXDelta="-10"
              android:interpolator="@android:anim/linear_interpolator"
              android:repeatCount="5"
              android:repeatMode="reverse"
              android:toXDelta="10" />
      </set>
      

      然后在代码中

      if (TextUtils.isEmpty(phone.getText())
       || phone.getText().length() < 10)
          {
           //shake animation
          phone.startAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.shake));
           }
      

      【讨论】:

        【解决方案6】:

        我在 Android 上创建了一个抖动效果并发布在 GitHub 上。看看效果是否更好。

        https://github.com/teoinke/ShakeAnimation

        相关代码:

        <?xml version="1.0" encoding="utf-8"?>
        <set
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:interpolator="@android:anim/overshoot_interpolator"
            android:fillAfter="true">
        
            <translate
                android:startOffset="100"
                android:fromXDelta="0%p"
                android:toXDelta="10%p"
                android:duration="50" />
        
            <translate
                android:startOffset="150"
                android:fromXDelta="0%p"
                android:toXDelta="-25%p"
                android:duration="110" />
        
        
            <translate
                android:startOffset="260"
                android:fromXDelta="0%p"
                android:toXDelta="25%p"
                android:duration="120" />
        
        
            <translate
                android:startOffset="380"
                android:fromXDelta="0%p"
                android:toXDelta="-20%p"
                android:duration="130" />
        
        
            <translate
                android:startOffset="510"
                android:fromXDelta="0%p"
                android:toXDelta="10%p"
                android:duration="140" />
        
        </set>
        

        【讨论】:

        • 对我来说这是最好的答案,因为它从中心开始动画并且不会像其他一些建议那样立即偏移图像。亲!
        【解决方案7】:

        这个作为 iOS“不正确的 PIN”摇动克隆效果很好(虽然不完美):

            final float FREQ = 3f;
            final float DECAY = 2f;
            // interpolator that goes 1 -> -1 -> 1 -> -1 in a sine wave pattern.
            TimeInterpolator decayingSineWave = new TimeInterpolator() {
                        @Override
                        public float getInterpolation(float input) {
                            double raw = Math.sin(FREQ * input * 2 * Math.PI);
                            return (float)(raw * Math.exp(-input * DECAY));
                        }
                    };
        
            shakeField.animate()
                    .xBy(-100)
                    .setInterpolator(decayingSineWave)
                    .setDuration(500)
                    .start();
        

        【讨论】:

          【解决方案8】:
          /**
           *
           * @param view      view that will be animated
           * @param duration  for how long in ms will it shake
           * @param offset    start offset of the animation
           * @return          returns the same view with animation properties
           */
          public static View makeMeShake(View view, int duration, int offset) {
              Animation anim = new TranslateAnimation(-offset,offset,0,0);
              anim.setDuration(duration);
              anim.setRepeatMode(Animation.REVERSE);
              anim.setRepeatCount(5);
              view.startAnimation(anim);
              return view;
          }
          

          使用:

          TextView tv;
          makeMeShake(tv,20,5);    // it will shake quite fast
          

          【讨论】:

          • 完美运行,速度非常快。
          【解决方案9】:

          对于 Kotlin 用户:

          首先创建一个名为 shake.xml 的动画资源文件。右键单击 Android Studio 中的 res 文件夹,然后单击 New > Android Resource File > 输入 shake 作为文件名,然后选择 Animation 作为 Resource type 下拉菜单。点击确定。

          shake.xml 中粘贴以下内容:

          <?xml version="1.0" encoding="utf-8"?>
          <set xmlns:android="http://schemas.android.com/apk/res/android">
              <translate android:duration="200"
                         android:fromXDelta="-5%"
                         android:repeatCount="3"
                         android:repeatMode="reverse"
                         android:toXDelta="5%"/>
          </set>
          

          现在只需在视图上调用它!

          从片段内:

          myView.startAnimation(AnimationUtils.loadAnimation(view!!.context, R.anim.shake))
          

          从活动中:

          myView.startAnimation(AnimationUtils.loadAnimation(this, R.anim.shake))
          

          (注意 - myView 是赋予您要制作动画的视图的 ID)

          如果您想微调动画,只需修改shake.xml 中的值即可。

          【讨论】:

          • startAnimationanim(在R.anim.shake 内)都是未解析的引用,请您帮忙?谢谢
          • 你需要在res目录@Maff中创建anim文件夹
          【解决方案10】:

          我创建了一个非常好的 iOS 抖动近似值(当您长按图标从主屏幕中删除应用程序时)。您必须以编程方式在代码中应用,因为它需要生成随机数:

          int dur1 = 70 + (int)(Math.random() * 30);
          int dur2 = 70 + (int)(Math.random() * 30);
          
          // Create an animation instance
          Animation an = new RotateAnimation(-3, 3, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
          
          // Set the animation's parameters
          an.setDuration(dur1);               // duration in ms
          an.setRepeatCount(-1);                // -1 = infinite repeated
          an.setRepeatMode(Animation.REVERSE);
          an.setFillAfter(true);               // keep rotation after animation
          
          
          // Create an animation instance
          Animation an2 = new TranslateAnimation(-TranslateAnimation.RELATIVE_TO_SELF,0.02f,
                  TranslateAnimation.RELATIVE_TO_SELF,0.02f,
                  -TranslateAnimation.RELATIVE_TO_SELF,0.02f,
                  TranslateAnimation.RELATIVE_TO_SELF,0.02f);
          
          // Set the animation's parameters
          an2.setDuration(dur2);               // duration in ms
          an2.setRepeatCount(-1);                // -1 = infinite repeated
          an2.setRepeatMode(Animation.REVERSE);
          an2.setFillAfter(true);               // keep rotation after animation
          
          AnimationSet s = new AnimationSet(false);//false means don't share interpolators
          s.addAnimation(an);
          s.addAnimation(an2);
          
          // Apply animation to image view
          itemView.setAnimation(s);
          

          此代码设计用于在适配器的网格视图 (getView) 中应用,但您可以通过将最后一行更改为:

          yourViewName.setAnimations(s);

          【讨论】:

          • 好像什么都没做
          • 请记住,这仅在 itemView 尚未添加到 ViewGroup 时才有效。如果已添加,请改用itemView.startAnimation(s)
          【解决方案11】:

          lincolnq's 答案的 Kotlin 版本

          val FREQ = 3f
          val DECAY = 2f
                      
          val decayingSineWave = TimeInterpolator { input ->
             val raw = sin(FREQ * input * 2 * Math.PI)
             (raw * exp((-input * DECAY).toDouble())).toFloat()
          }
          
          // where binding.loginFrame is the view you wanna shake
          binding.loguinFrame.animate()
           .withEndAction{
              // here you can clear the fields after the shake
           }
           .xBy(-100f)
           .setInterpolator(decayingSineWave)
           .setDuration(500)
           .start()
          

          【讨论】:

            【解决方案12】:

            IOS摆动动画不是那么简单尝试在旋转时随机改变轴心x和y。不过,您应该以编程方式更改该值。也许你也可以同时使用翻译动画

            【讨论】:

              【解决方案13】:

              敲了两个多小时的头,我知道如何摇晃视线。

              不幸的是,除了片段的 onCreateView 之外,接受的答案将不起作用。

              如果你有 onClick 方法并在里面,例如。你有像下面这样的动画它不会工作。

              请检查代码。

                  DoneStart.setOnClickListener(new OnClickListener() {
              
                      @Override
                      public void onClick(View view) {
                         register(view);
              
                      }
                  });
              

              注册方法有一些检查,如下代码

               private void register(View view) {
                  String type = typedThings.getText.toString(); 
                 String  km = Km_Now.getText().toString();
              
                  if (serviceType == null) {
                      animationServiceList = AnimationUtils.loadAnimation(getActivity(), R.anim.shake_wobble);
                      silverServiceButton.setAnimation(animationServiceList);
                      generalServiceButton.setAnimation(animationServiceList);
                      platinumServiceButton.setAnimation(animationServiceList);
                      animationServiceList.start();
                  } else if (km == null) {
                      animationEditText = AnimationUtils.loadAnimation(getActivity(), R.anim.shake_wobble);
                      Km_Now.setAnimation(animationEditText);
                      animationEditText.start();
                  }
              

              调用animationServiceList.start();永远不会被调用,

              解决方案:像 ObjectAnimator 一样使用 PropertyAnimator。

              【讨论】:

                【解决方案14】:

                其他答案也是正确的,但这比他们更平滑,因为它使用插值器为来回运动产生平滑的数字

                    public class WobblyView extends ImageView implements ValueAnimator.AnimatorUpdateListener {
                    private final ValueAnimator va = ValueAnimator.ofInt(-10, 10);
                
                    public WobblyView(Context context) {
                        this(context, null);
                    }
                
                    public WobblyView(Context context, @Nullable AttributeSet attrs) {
                        this(context, attrs, 0);
                    }
                
                    public WobblyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
                        super(context, attrs, defStyleAttr);
                        setAdjustViewBounds(true);
                        setImageResource(R.drawable.ic_logo);
                        va.setInterpolator(new AccelerateDecelerateInterpolator());
                        va.setRepeatMode(ValueAnimator.REVERSE);
                        va.setRepeatCount(ValueAnimator.INFINITE);
                        va.setDuration(1000);
                    }
                
                    @Override
                    protected void onAttachedToWindow() {
                        super.onAttachedToWindow();
                        va.addUpdateListener(this);
                        va.start();
                    }
                
                    @Override
                    protected void onDetachedFromWindow() {
                        super.onDetachedFromWindow();
                        va.removeUpdateListener(this);
                    }
                
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        int heading = (int) animation.getAnimatedValue();
                        setRotation(heading);
                    }
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2016-11-03
                  • 1970-01-01
                  • 2011-10-24
                  • 2015-08-08
                  • 2022-12-18
                  • 2012-09-24
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多