Android 旋转图像。动画列表还是动画旋转?(安卓)

Android 旋转图像。动画列表还是动画旋转?(安卓),android,animation,rotation,Android,Animation,Rotation,我想创建一个旋转的进度图像,并想知道最好的方式是什么。我可以使用动画列表,例如每100毫秒更改12幅图像。这很好,但创建12幅图像或针对每种大小和分辨率创建12幅图像非常繁琐: <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/ic_loading_grey_on

我想创建一个旋转的进度图像,并想知道最好的方式是什么。我可以使用动画列表,例如每100毫秒更改12幅图像。这很好,但创建12幅图像或针对每种大小和分辨率创建12幅图像非常繁琐:

<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
<item android:drawable="@drawable/ic_loading_grey_on_black_01" android:duration="100" />
<item android:drawable="@drawable/ic_loading_grey_on_black_02" android:duration="100" />
<item android:drawable="@drawable/ic_loading_grey_on_black_03" android:duration="100" />
<item android:drawable="@drawable/ic_loading_grey_on_black_04" android:duration="100" />
<item android:drawable="@drawable/ic_loading_grey_on_black_05" android:duration="100" />
<item android:drawable="@drawable/ic_loading_grey_on_black_06" android:duration="100" />
<item android:drawable="@drawable/ic_loading_grey_on_black_07" android:duration="100" />
<item android:drawable="@drawable/ic_loading_grey_on_black_08" android:duration="100" />
<item android:drawable="@drawable/ic_loading_grey_on_black_09" android:duration="100" />
<item android:drawable="@drawable/ic_loading_grey_on_black_10" android:duration="100" />
<item android:drawable="@drawable/ic_loading_grey_on_black_11" android:duration="100" />
<item android:drawable="@drawable/ic_loading_grey_on_black_12" android:duration="100" />

我认为一个更简单的解决方案是每个分辨率使用一个图像,而不是为每个帧旋转它。在平台资源(android sdk windows/platform…)中,我在drawable/search_spinner.xml文件中找到了一个名为animated rotate的东西,但是如果我复制代码,就会出现一个编译器错误,抱怨android:FrameScont和android:frameDuration(Eclipse中的Google API 2.2):


我也尝试过使用重复旋转动画(在“动画资源”文件夹中使用),但实际上我更喜欢动画列表版本的外观


解决此问题的推荐方法是什么?

您必须创建一个可绘制的xml文件,如下所示:

代码:


参见此处的示例

具体而言: 进度条

  • 增量的 演示可以以单位递增或递减的大小旋转进度指示器
  • 光滑的 演示用于指示通用“忙”消息的大小连续旋转进度指示器
  • 对话 演示ProgressDialog,这是一个承载进度条的弹出对话框。此示例演示了确定和不确定的进度指标
  • 在标题栏中 演示通过设置WindowPolicy的进度指示器功能加载进度指示器的活动屏幕
    SACPK的解决方案肯定有效。另一个解决方案是像前面提到的那样使用
    ,并删除
    android:framescont=“12”
    android:frameDuration=“100”
    编译器投诉的属性。它仍然适用于我的8帧图像


    但是,我还没有弄明白如何控制动画的速度:(。

    Praveen建议的Rotate drawable
    无法控制帧数。假设您想要实现一个自定义加载程序,它由8个部分组成:

    使用
    动画列表
    方法,您需要手动创建按
    45*帧数
    度旋转的8帧。或者,您可以使用第一帧并将旋转动画设置为:

    文件
    res/anim/progress\u anim.xml

    <?xml version="1.0" encoding="utf-8"?>
    <rotate
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:fromDegrees="0"
        android:toDegrees="360"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="infinite" />
    
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="ProgressView">
            <attr name="frameCount" format="integer"/>
            <attr name="duration" format="integer" />
        </declare-styleable>
    </resources>
    
    <com.example.widget.ProgressView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_progress" 
        app:frameCount="8"
        app:duration="1000"/>
    
    这将为您提供平滑动画,而不是8步动画。要解决此问题,我们需要实现自定义插值器:

    a.setInterpolator(new Interpolator() {
        private final int frameCount = 8;
    
        @Override
        public float getInterpolation(float input) {
            return (float)Math.floor(input*frameCount)/frameCount;
        }
    });
    
    您还可以创建自定义小部件:

    文件
    res/values/attrs.xml

    <?xml version="1.0" encoding="utf-8"?>
    <rotate
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:fromDegrees="0"
        android:toDegrees="360"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="infinite" />
    
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="ProgressView">
            <attr name="frameCount" format="integer"/>
            <attr name="duration" format="integer" />
        </declare-styleable>
    </resources>
    
    <com.example.widget.ProgressView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_progress" 
        app:frameCount="8"
        app:duration="1000"/>
    
    文件
    activity\u main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <rotate
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:fromDegrees="0"
        android:toDegrees="360"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="infinite" />
    
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="ProgressView">
            <attr name="frameCount" format="integer"/>
            <attr name="duration" format="integer" />
        </declare-styleable>
    </resources>
    
    <com.example.widget.ProgressView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_progress" 
        app:frameCount="8"
        app:duration="1000"/>
    
    
    

    文件
    res/anim/progress\u anim.xml
    :上面列出的我发现vokilam的答案是创建一个好的阶梯/交错动画的最佳答案。我采纳了他的最后建议,制作了一个自定义小部件,我遇到的唯一问题是设置可见性不起作用,因为它是动画的,因此总是可见的

    我将他的代码(ProgressView.java,我将其重命名为StaggeredProgress.java)调整如下:

    public class StaggeredProgress extends ImageView {
    
    private Animation staggered;
    
    public StaggeredProgress(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setAnimation(attrs);
    }
    
    public StaggeredProgress(Context context, AttributeSet attrs) {
        super(context, attrs);
        setAnimation(attrs);
    }
    
    public StaggeredProgress(Context context) {
        super(context);
    }
    
    private void setAnimation(AttributeSet attrs) {
        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.StaggeredProgress);
        int frameCount = a.getInt(R.styleable.StaggeredProgress_frameCount, 12);  
        int duration = a.getInt(R.styleable.StaggeredProgress_duration, 1000);
        a.recycle();
    
        setAnimation(frameCount, duration);
    }
    
    public void setAnimation(final int frameCount, final int duration) {
        Animation a = AnimationUtils.loadAnimation(getContext(), R.anim.progress_anim);
        a.setDuration(duration);
        a.setInterpolator(new Interpolator() {
    
            @Override
            public float getInterpolation(float input) {
                return (float)Math.floor(input*frameCount)/frameCount;
            }
        });
        staggered = a;
        //startAnimation(a);
    }
    
    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        if( visibility == View.VISIBLE )
            startAnimation(staggered);
        else
            clearAnimation();
    
    }
    
    
    }
    

    通过这种方式设置视图的可见性可以根据需要启动和停止动画…再次感谢vokilam!

    感谢@vokilam。这种类似的解决方案(自动旋转的自定义视图)使用
    。
    */
    私有静态类RotatedDrawable扩展了BitmapDrawable{
    私人最终浮动学位;
    私有int-pivotX;
    私有整数枢轴;
    可旋转绘制(位图、浮动度、资源分辨率){
    超级(分辨率,位图);
    pivotX=bitmap.getWidth()/2;
    pivotY=bitmap.getHeight()/2;
    这个。度=度;
    }
    @覆盖公共空白绘制(最终画布){
    canvas.save();
    画布。旋转(度、轴、轴);
    超级绘画(画布);
    canvas.restore();
    }
    }
    /**
    *看。
    */
    @非空私有静态位图drawableToBitmap(DrawableDrawable){
    最终位图Bitmap=Bitmap.createBitmap(drawable.getIntrinsicWidth()、drawable.getIntrinsicHeight()、Bitmap.Config.ARGB_8888);
    最终画布=新画布(位图);
    drawable.setBounds(0,0,canvas.getWidth(),canvas.getHeight());
    可绘制。绘制(画布);
    返回位图;
    }
    }
    

    请参阅以获取完整(可能更更新)的源代码。

    我无法使用
    android:visibility=“invisible”
    隐藏progressview。有什么原因吗?这是一个很好的解释,谢谢!对于那些使用插值器有问题的人,我只使用了:a.setInterpolator(new LinearInterpolator());而且效果很好!如何强制停止动画?有用的进展为什么它不旋转?它在某些设备上不工作。请改用旋转