バー自体が水平方向に進むにつれて垂直方向に回転するプログレスバーを作成しようとしています。プログレスドローアブルをドローアブルとして使用しています。
<ProgressBar
Android:id="@+id/progressBar"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
style="@Android:style/Widget.ProgressBar.Horizontal"
Android:progressDrawable="@drawable/custom_progress"
Android:layout_marginRight="5dp" />
これが私のドローアブルです:
でも、進行するにつれて微妙なロール効果が欲しいです。したがって、垂直線が後方に移動しているように見えます。フォローしますか?どんな助けでも大歓迎です。ありがとう。
編集:進行状況の描画可能としてアニメーションリストを作成しようとしましたが、それでもアニメーションを表示できません。アニメーションリストを進行状況アイテムのクリップ内に含めることはできますか?
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:id="@Android:id/background" Android:drawable="@drawable/Gutter"></item>
<item Android:id="@Android:id/progress">
<clip>
<animation-list Android:oneshot="false">
<item Android:drawable="@drawable/progress_bar_animate" Android:duration="100" />
<item Android:drawable="@drawable/progress_bar_animate2" Android:duration="100" />
<item Android:drawable="@drawable/progress_bar_animate3" Android:duration="100" />
<item Android:drawable="@drawable/progress_bar_animate4" Android:duration="100" />
<item Android:drawable="@drawable/progress_bar_animate5" Android:duration="100" />
<item Android:drawable="@drawable/progress_bar_animate6" Android:duration="100" />
<item Android:drawable="@drawable/progress_bar_animate7" Android:duration="100" />
</animation-list>
</clip>
</item>
</layer-list>
私はこれが私が思ったようにできるとは思いません。その理由は、その時点でClipDrawableであるanimated-listを参照して、プログラムでアニメーションを開始できるようにするために必要なAnimateDrawableにキャストできないためです。また、ProgressBarが画像をマスクして、進行中の画像の一部のみを表示するようにするため、クリップ要素に含める必要があります。
ImageViewsを使用して自分のプログレスバーを偽造し、それらをアニメーション化することを除けば、この特定のプログレスバーの周りに別の方法はありません。
Yahoo!最後に !動作します! (ただし、!!!!大きな画像ではメモリリークが発生する可能性があります。以下の投稿で修正されています)
このコードは、タイル画像(tile1)を取得し、それを繰り返し(TileMode.REPEAT)、シフトされたアニメーション(10フラグメント)を作成し、これをアニメーションセットに追加します。
private void initAnimation() {
// R.drawable.tile1 is PNG
Bitmap b = BitmapFactory.decodeResource(getResources(),R.drawable.tile1);
AnimationDrawable shiftedAnimation = getAnimation(b);
// R.id.img_3 is ImageView in my application
View v = findViewById(R.id.img_3);
v.setBackground(shiftedAnimation);
shiftedAnimation.start();
}
private Bitmap getShiftedBitmap(Bitmap bitmap, int shiftX) {
Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
Canvas newBitmapCanvas = new Canvas(newBitmap);
Rect srcRect1 = new Rect(shiftX, 0, bitmap.getWidth(), bitmap.getHeight());
Rect destRect1 = new Rect(srcRect1);
destRect1.offset(-shiftX, 0);
newBitmapCanvas.drawBitmap(bitmap, srcRect1, destRect1, null);
Rect srcRect2 = new Rect(0, 0, shiftX, bitmap.getHeight());
Rect destRect2 = new Rect(srcRect2);
destRect2.offset(bitmap.getWidth() - shiftX, 0);
newBitmapCanvas.drawBitmap(bitmap, srcRect2, destRect2, null);
return newBitmap;
}
private List<Bitmap> getShiftedBitmaps(Bitmap bitmap) {
List<Bitmap> shiftedBitmaps = new ArrayList<Bitmap>();
int fragments = 10;
int shiftLength = bitmap.getWidth() / fragments;
for(int i = 0 ; i < fragments; ++i){
shiftedBitmaps.add( getShiftedBitmap(bitmap,shiftLength * i));
}
return shiftedBitmaps;
}
private AnimationDrawable getAnimation(Bitmap bitmap) {
AnimationDrawable animation = new AnimationDrawable();
animation.setOneShot(false);
List<Bitmap> shiftedBitmaps = getShiftedBitmaps(bitmap);
int duration = 50;
for(Bitmap image: shiftedBitmaps){
BitmapDrawable navigationBackground = new BitmapDrawable(getResources(), image);
navigationBackground.setTileModeX(TileMode.REPEAT);
animation.addFrame(navigationBackground, duration);
}
return animation;
}
これは私が得るものです。
そしてこれは方法です:
<ProgressBar
Android:layout_width="match_parent"
Android:layout_height="15dp"
Android:indeterminate="true"
style="@style/IndeterminateProgressBar" />
その後、styles.xmlで:
<style name="IndeterminateProgressBar" parent="@Android:style/Widget.ProgressBar.Horizontal">
<item name="Android:indeterminateDrawable">@anim/progress_bar_indeterminate</item>
</style>
ファイルres/anim/progress_bar_indeterminate.xml:
<?xml version="1.0" encoding="utf-8"?>
<animation-list
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:oneshot="false">
<item Android:drawable="@drawable/progress_bar_horizontal_1" Android:duration="200" />
<item Android:drawable="@drawable/progress_bar_horizontal_2" Android:duration="200" />
<item Android:drawable="@drawable/progress_bar_horizontal_3" Android:duration="200" />
<item Android:drawable="@drawable/progress_bar_horizontal_4" Android:duration="200" />
</animation-list>
そしてここにres/drawableフォルダに入れる必要がある4つの画像:
P.S.プログレスバーの方向を逆にする必要がある場合は、progress_bar_indeterminate.xmlの画像の名前の数字を反転するだけです。
良い一日! =)
以前の方法では、メモリの消費に問題がありました。 TranslateAnimationを使用するように改善しました。しかし、LAGはほとんどありません(ProgressBgView.initAnimationメソッドのHACKコメントに注意してください)
レイアウトxml:
<com.example.tweenanimation.ProgressBgView
Android:layout_height="wrap_content"
Android:layout_width="match_parent"
Android:id="@+id/progress_db_view"
/>
バックエンド:
final ProgressBgView prog = (ProgressBgView) findViewById(R.id.progress_db_view);
prog.setBackgroundAsTile(R.drawable.bg_tile_1);
prog.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
prog.startAnimation();
}
});
そしてクラス:
public class ProgressBgView extends FrameLayout {
private ImageView mProgressImage;
private TranslateAnimation mProgressAnimation;
public ProgressBgView(Context context, AttributeSet attrs) {
super(context, attrs);
mProgressImage = new ImageView(getContext());
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
mProgressImage.setLayoutParams(layoutParams);
addView(mProgressImage);
}
public void setBackgroundAsTile(int tileImageResId) {
Bitmap tileBitmap = BitmapFactory.decodeResource(getResources(), tileImageResId);
BitmapDrawable tileRepeatedBitmap = new BitmapDrawable(getResources(), tileBitmap);
tileRepeatedBitmap.setTileModeX(TileMode.REPEAT);
initAnimation(tileBitmap.getWidth());
mProgressImage.setBackgroundDrawable(tileRepeatedBitmap);
}
private void initAnimation(int tileImageWidth) {
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mProgressImage.getLayoutParams();
layoutParams.setMargins(-tileImageWidth, 0, 0, 0);
// *HACK* tileImageWidth-3 is used because of *lags*(slow pause) in the moment
// of animation END-RESTART.
mProgressAnimation = new TranslateAnimation(0, tileImageWidth - 3, 0, 0);
mProgressAnimation.setInterpolator(new LinearInterpolator());
mProgressAnimation.setDuration(1000);
mProgressAnimation.setRepeatCount(Animation.INFINITE);
}
public void startAnimation() {
mProgressImage.startAnimation(mProgressAnimation);
}
}
私は解決策を見つけました。次のように、progress_loading.xmlなどのxmlを作成し、プログレスバーのプログレスドローアブルに割り当てます。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android" >
<item Android:id="@Android:id/progress">
<clip>
<shape>
<solid Android:color="#33FFFFFF" />
</shape>
</clip>
</item>
</layer-list>
次にコードで:
AnimationDrawable anim = (AnimationDrawable) getResources()
.getDrawable(R.drawable.loading);
ClipDrawable clipDrawable = new ClipDrawable(anim, Gravity.LEFT,
ClipDrawable.HORIZONTAL);
LayerDrawable layerDrawable = (LayerDrawable) progressBar
.getProgressDrawable();
layerDrawable.setDrawableByLayerId(Android.R.id.progress,
clipDrawable);
anim.start();
Xmlloading.xmlに実際のanimation-listがある場合。これは私のために働いています。
プログレスバーを確定させたい人のために、user1269737の回答に改善点を投稿します。
私はこのようにintAnimationメソッドを変更しました:
private void initAnimation(int tileImageResId) {
Bitmap b = BitmapFactory.decodeResource(getResources(), tileImageResId);
if (b != null) {
shiftedAnimation = getAnimation(b);
setBackgroundColor(ContextCompat.getColor(getContext(), #14000000));
mProgressImage.setBackground(shiftedAnimation);
}
}
そして、アニメーション化された進行状況の変更を伴うsetProgressメソッドが追加されました。
public void setProgress(double progress){
if (progress > 100){
progress = 100;
}
else if (progress < 0){
progress = 0;
}
int parentWidth = getWidth();
final int newWidth = (int)(parentWidth*(progress/100.0));
widthAnimator = ValueAnimator.ofInt(mProgressImage.getLayoutParams().width, newWidth);
widthAnimator.setDuration(200);
widthAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mProgressImage.getLayoutParams().width = (Integer) animation.getAnimatedValue();
mProgressImage.requestLayout();
}
});
widthAnimator.start();
}
そしてコンストラクターのいくつかの変更:
public LProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
mProgressImage = new ImageView(getContext());
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(0, FrameLayout.LayoutParams.MATCH_PARENT);
mProgressImage.setLayoutParams(layoutParams);
addView(mProgressImage);
initAnimation(R.drawable.pb_background);
}
download_progress_anim.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item
Android:drawable="@drawable/stripe3"
Android:duration="100"/>
<item
Android:drawable="@drawable/stripe2"
Android:duration="100"/>
<item
Android:drawable="@drawable/stripe1"
Android:duration="100"/>
</animation-list>
Javaコード:
mDownloadProgressBar.setProgressDrawable(createProgressDrawable(context));
private Drawable createProgressDrawable(Context context) {
ShapeDrawable shape = new ShapeDrawable();
shape.getPaint().setStyle(Paint.Style.FILL);
shape.getPaint()
.setColor(ContextCompat.getColor(context, R.color.black_20));
AnimationDrawable animationDrawable = (AnimationDrawable) getDrawable(R.drawable.download_progress_anim, context);
ClipDrawable clipDrawable = new ClipDrawable(animationDrawable, Gravity.LEFT, ClipDrawable.HORIZONTAL);
animationDrawable.start();
LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{shape, clipDrawable});
layerDrawable.setId(0, Android.R.id.background);
layerDrawable.setId(1, Android.R.id.progress);
return layerDrawable;
}
private Drawable getDrawable(@DrawableRes int drawable, Context context) {
if (Build.VERSION.SDK_INT < 21) {
return context.getResources().getDrawable(drawable);
} else {
return context.getResources().getDrawable(drawable, null);
}
}
それが役に立てば幸い。独自の実装をサポートするように簡単に変更できます。
私は、上記の説明に似ているが、それから生じたものではない1つの解決策を見つけました。よく働く!
以下はprogress_drawable.xmlです。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:id="@Android:id/background">
<shape>
<solid
Android:color="@color/black_20"/>
</shape>
</item>
<item Android:id="@Android:id/progress">
<clip>
<animation-list
Android:oneshot="false">
<item
Android:drawable="@drawable/stripe3"
Android:duration="100"/>
<item
Android:drawable="@drawable/stripe2"
Android:duration="100"/>
<item
Android:drawable="@drawable/stripe1"
Android:duration="100"/>
</animation-list>
</clip>
</item>
</layer-list>
次に、Javaコードで、次の手順を実行します。
mDownloadProgressBar.setProgressDrawable(getResources().getDrawable(R.drawable.download_progress, null));
LayerDrawable drawable = (LayerDrawable)mDownloadProgressBar.getProgressDrawable();
ClipDrawable clipDrawable = (ClipDrawable) drawable.getDrawable(1);
AnimationDrawable animationDrawable =(AnimationDrawable)clipDrawable.getDrawable();
animationDrawable.start();