回転進行イメージを作成したいのですが、どのように進めるのが最善かと思います。たとえば、100ミリ秒ごとに変化する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" />
より簡単な解決策は、解像度ごとに1つの画像を使用することですが、フレームごとに画像を回転させることです。プラットフォームリソース(Android-sdk-windows/platforms ...)で、ファイルdrawable/search_spinner.xmlにanimated-rotateと呼ばれるものが見つかりましたが、コードをコピーすると、Android:framesCountとAndroidについて不平を言うコンパイラエラーが発生します。 frameDuration(EclipseのGoogle API 2.2):
<animated-rotate xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:drawable="@drawable/spinner_black_20"
Android:pivotX="50%"
Android:pivotY="50%"
Android:framesCount="12"
Android:frameDuration="100" />
また、繰り返し回転アニメーション(animリソースフォルダーで使用)を使用しようとしましたが、実際にはアニメーションリストバージョンの外観を好みます。
この問題を解決する推奨される方法は何ですか?
Praveenが提案したRotate drawable
では、フレームカウントを制御できません。 8つのセクションで構成されるカスタムローダーを実装するとします。
animation-list
アプローチを使用して、45*frameNumber
度回転した8つのフレームを手動で作成する必要があります。または、最初のフレームを使用して、それに回転アニメーションを設定できます。
ファイルres/anim/progress_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" />
ファイルMainActivity.Java
Animation a = AnimationUtils.loadAnimation(getContext(), R.anim.progress_anim);
a.setDuration(1000);
imageView.startAnimation(a);
これにより、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"?>
<resources>
<declare-styleable name="ProgressView">
<attr name="frameCount" format="integer"/>
<attr name="duration" format="integer" />
</declare-styleable>
</resources>
ファイルProgressView.Java
:
public class ProgressView extends ImageView {
public ProgressView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setAnimation(attrs);
}
public ProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
setAnimation(attrs);
}
public ProgressView(Context context) {
super(context);
}
private void setAnimation(AttributeSet attrs) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ProgressView);
int frameCount = a.getInt(R.styleable.ProgressView_frameCount, 12);
int duration = a.getInt(R.styleable.ProgressView_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;
}
});
startAnimation(a);
}
}
ファイルactivity_main.xml
:
<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_anim.xml
:上記のリスト
以下のようなドローアブルxmlファイルを作成する必要があります。
コード:
<animated-rotate xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:pivotX="50%" Android:pivotY="50%" Android:fromDegrees="0"
Android:toDegrees="360" Android:drawable="@drawable/imagefile_to_rotate" />
ニースのステップ/スタッガードアニメーションを作成するには、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に感謝します!
こちらの例をご覧ください http://developer.Android.com/resources/samples/ApiDemos/src/com/example/Android/apis/view/index.html
具体的には、進行状況バー
@vokilamに感謝します。この同様のソリューション(自動的に回転するカスタムビュー)では、<animation-list>
実装で動的に:
public class FramesAnimatorView extends AppCompatImageView {
private int framesCount;
private int duration;
private Bitmap frameBitmap;
public FramesAnimatorView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
public FramesAnimatorView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public FramesAnimatorView(Context context) { super(context); }
private void init(Context context, AttributeSet attrs) {
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FramesAnimatorView);
framesCount = typedArray.getInt(R.styleable.FramesAnimatorView_framesCount, 12);
duration = typedArray.getInt(R.styleable.FramesAnimatorView_duration, 1200);
typedArray.recycle();
// Method 1: Use <rotate> as Animation (RotateAnimation) and startAnimation() (Rotate view itself).
//method1(framesCount, duration);
// Method 2: Use <rotate> as Drawable (RotateDrawable) and ObjectAnimator. Usable for API 21+ (because of using RotateDrawable.setDrawable).
//method2();
// Method 3 (Recommended): Use <animation-list> (AnimationDrawable) dynamically.
final int frameDuration = this.duration / framesCount;
final AnimationDrawable animationDrawable = (AnimationDrawable) getDrawable();
for (int i = 0; i < framesCount; i++)
animationDrawable.addFrame(
new RotatedDrawable(frameBitmap, i * 360f / framesCount, getResources()),
frameDuration);
animationDrawable.start();
}
@Override public void setImageResource(int resId) { //info();
frameBitmap = BitmapFactory.decodeResource(getResources(), resId);
super.setImageDrawable(new AnimationDrawable());
}
@Override public void setImageDrawable(@Nullable Drawable drawable) { //info();
frameBitmap = drawableToBitmap(drawable);
super.setImageDrawable(new AnimationDrawable());
}
@Override public void setImageBitmap(Bitmap bitmap) { //info();
frameBitmap = bitmap;
super.setImageDrawable(new AnimationDrawable());
}
/**
* See <a href="https://stackoverflow.com/a/21376008/5318303">@Android-developer's answer on stackoverflow.com</a>.
*/
private static class RotatedDrawable extends BitmapDrawable {
private final float degrees;
private int pivotX;
private int pivotY;
RotatedDrawable(Bitmap bitmap, float degrees, Resources res) {
super(res, bitmap);
pivotX = bitmap.getWidth() / 2;
pivotY = bitmap.getHeight() / 2;
this.degrees = degrees;
}
@Override public void draw(final Canvas canvas) {
canvas.save();
canvas.rotate(degrees, pivotX, pivotY);
super.draw(canvas);
canvas.restore();
}
}
/**
* See <a href="https://stackoverflow.com/a/10600736/5318303">@André's answer on stackoverflow.com</a>.
*/
@NonNull private static Bitmap drawableToBitmap(Drawable drawable) {
final Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
}
完全な(およびおそらくより更新された)ソースコードについては、 GitHubのAndroid-FramesAnimatorView を参照してください。
SACPKのソリューションは間違いなく機能します。別の解決策は、<animated-rotate>
質問と同じように削除してAndroid:framesCount="12" Android:frameDuration="100"
コンパイラーが不平を言うそれらの属性。 8フレームの画像でも機能します。
ただし、アニメーションの速度を制御する方法がわかりませんでした:(。