在安卓中实现抖动/摇晃视图动画

100

我创建了一个类似于下面的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" />
15个回答

184

尝试设置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
@N.K:它应该与Java中的工作方式相同:通过其资源ID加载动画,并通过将其作为参数传递来告诉您的视图启动动画。应该看起来像这样:view.StartAnimation(AnimationUtils.LoadAnimation(Resource.Animation.wobble))。更多细节请参见此处此处 - MH.
3
我们如何在摇晃之间添加延迟?例如显示500毫秒的摇晃,然后延迟1000毫秒,然后再次重复? - Damir Mailybayev

105

漂亮的震动动画;

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));

5
据我看来,android:duration="50" 看起来更加流畅,而且效果更好。 - Ali Bdeir

48

您可以尝试这个:

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" />

12
嘿,我猜cycle_7.xml可以替换为<translate .../>标签中的android:repeatCount="7"属性。 - Anup

28

试着使用这个:

<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>

21

要做出像这样的晃动效果

enter image description here

首先在 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));
     }

16

我在安卓上创建了抖动效果,并发布在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>

1
对我来说,这是最好的答案,因为它从中心开始动画,不像其他建议那样立即偏移图像。专业! - Jonathan Dunn

14

这个方法作为iOS的“密码错误震动”克隆效果还不错(虽然不是完美的):

    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();

12
/**
 *
 * @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

2
完美运行,速度非常快。 - George Vrynios

11

对于Kotlin用户:

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

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(requireContext(), R.anim.shake))
在一个活动中,从内部开始:
myView.startAnimation(AnimationUtils.loadAnimation(this, R.anim.shake))

注意 - myView是您想要进行动画处理的视图的ID。

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


startAnimationanim(在R.anim.shake中)都是未解决的引用,请问你能帮忙吗?谢谢。 - Maff
你需要在res目录下创建一个名为anim的文件夹。@Maff - Aditya Patil

3

我创建了一个非常好的类似于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);

这段代码旨在应用于适配器的gridview (getView)中,但是您可以通过更改最后一行将其应用于任何视图:

yourViewName.setAnimations(s);


似乎它什么也没做。 - user25
请记住,只有在itemView尚未添加到ViewGroup中时才能使用此方法。如果已经添加,请改用itemView.startAnimation(s) - Alex Semeniuk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接