Android: Пользовательская горизонтальная анимация Progress Bar

Я пытаюсь создать индикатор выполнения, в котором сам бар оживляет вертикальное вращение по горизонтали. Я успешно использую мой прогресс, который можно использовать в качестве переносимого с помощью:

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

Вот моя возможность:

Введите описание изображения здесь

Но я хочу, чтобы у него был тонкий эффект броска по мере его развития. Таким образом, это будет похоже на то, что вертикальные линии перемещаются назад sorta. Вы выполните? Буду признателен за любую оказанную помощь. Благодарю.

EDIT: Я попытался создать список анимации, поскольку мой прогресс доступен, но я все еще не могу видеть анимацию. Может ли список анимации находиться внутри клипа для элемента прогресса?

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

Solutions Collecting From Web of "Android: Пользовательская горизонтальная анимация Progress Bar"

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

Я не думаю, что это можно сделать так, как я думал. Причина в том, что я не могу ссылаться на анимированный список, который в этот момент является ClipDrawable, и отсылает его в AnimateDrawable, что необходимо, чтобы я мог программно запустить анимацию. Также необходимо содержать его в элементе клипа, поскольку это способ маскировки изображения ProgressBar, чтобы он отображал только часть изображения по мере его продвижения.

Помимо подделки моего собственного индикатора выполнения с помощью ImageViews и анимации, я не вижу другого пути вокруг этого конкретного ProgressBar.

У моего предыдущего метода была проблема с потреблением памяти. Я улучшил его, чтобы использовать TranslateAnimation. НО у него мало LAG (обратите внимание на комментарий HACK в методе ProgressBgView.initAnimation)

Макет 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); } } 

Это то, что я получаю. Пользовательский горизонтальный индикатор выполнения

И это так:

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

И вот 4 изображения, которые нужно положить в папку res / drawable:

progress_bar_horizontal_1

progress_bar_horizontal_2

progress_bar_horizontal_3

progress_bar_horizontal_4

PS Если вам нужно обратное направление индикатора выполнения, просто переверните числа в имени изображений в progress_bar_indeterminate.xml.

Добрый день! знак равно

Я нашел решение. Создайте xml, скажем, progress_loading.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(); 

Где xml load.xml имеет фактический список анимации. Это сработало для меня.

Я нашел одно решение, похожее на приведенное выше объяснение, но не возникшее из него. Прекрасно работает!

Скажем ниже, наш 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(); 

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

Надеюсь, поможет. Вы можете легко изменить его, чтобы поддержать свою собственную реализацию.