2012-12-20 25 views
12

Sto provando a creare una barra di avanzamento in cui la barra si anima in una rotazione verticale mentre avanza orizzontalmente. Sto usando con successo i miei progressi drawable come drawable via:Android: Barra di avanzamento orizzontale personalizzata Animazione

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

Ecco la mia disegnabile:

enter image description here

Ma voglio che per avere un effetto rotolo sottile come la sua progressione. Quindi sembrerebbe che le linee verticali si muovano all'indietro in qualche modo. Segui? Ogni aiuto è molto apprezzato. Grazie.

MODIFICA: Ho provato a creare un elenco di animazioni come il mio progresso disegnabile ma non riesco ancora a vedere l'animazione. Una lista di animazione può essere all'interno di una clip per l'elemento di progresso?

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

quindi qualcosa come http://2.bp.blogspot.com/-O7nsXfmgwSc/T6PQ0PVr6-I/AAAAAAAAAQI/-eXkEXj24-s/s1600/02.gif? –

+1

Esattamente come quello. – askilondz

risposta

2

Non penso che questo possa essere fatto nel modo in cui pensavo potesse farlo. Il motivo è che non posso fare riferimento alla lista animata, che a quel punto è un ClipDrawable, e lanciarlo su un AnimateDrawable, che è necessario in modo da poter avviare l'animazione a livello di codice. È anche necessario contenerlo nell'elemento clip in quanto è il modo di mascherare un'immagine di ProgressBar in modo che mostri solo parte dell'immagine mentre procede.

Oltre a simulare la mia barra di avanzamento utilizzando ImageView e animando quelli che non vedo in un altro modo intorno a questa ProgressBar specifica.

1

Ho trovato una soluzione. Creare un XML dire, progress_loading.xml come segue e assegnare al progresso drawable del progressbar:

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

Poi nel codice:

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

Qualora il loading.xml XML ha l'animation- effettivo elenco. Questo ha funzionato per me.

10

Yahoo! Finalmente ! Lavori ! (MA può causare perdita di memoria con immagini grandi. È stato risolto nel post seguente)

Questo codice prende l'immagine della tessera (tile1), la ripete (TileMode.REPEAT), rende l'animazione spostata (10 frammenti) , aggiunge questo nel set di animazione.

enter image description here

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

Lo applico solo su uno dei pulsanti del mio progetto, funziona perfettamente, grazie! :) –

+0

v.setBackground (shiftedAnimation) - funziona solo dal livello API 16 – AndrewS

1

Il mio metodo precedente aveva problemi con la memoria consumare. L'ho migliorato per usare TranslateAnimation. Ma ha poco GAL (prestare attenzione su HACK commentare nel metodo ProgressBgView.initAnimation)

xml Disposizione:

<com.example.tweenanimation.ProgressBgView 
     android:layout_height="wrap_content" 
     android:layout_width="match_parent" 
     android:id="@+id/progress_db_view" 
     /> 

backend:

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

E la classe:

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

Ho trovato che questa soluzione aveva problemi su Android 2.3 (l'ultima tessera stava saltando), la soluzione dal 3 aprile alle 13:24 stava lavorando anche su Gingerbread. – zilinx

1

Questo è ciò che ottengo. Custom horizontal progress bar

E questo è il modo:

<ProgressBar 
    android:layout_width="match_parent" 
    android:layout_height="15dp" 
    android:indeterminate="true" 
    style="@style/IndeterminateProgressBar" /> 

Dopo che nel styles.xml:

<style name="IndeterminateProgressBar" parent="@android:style/Widget.ProgressBar.Horizontal"> 
    <item name="android:indeterminateDrawable">@anim/progress_bar_indeterminate</item> 
</style> 

In res di file/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> 

E qui 4 immagini che devono essere messe in cartella res/drawable:

progress_bar_horizontal_1

progress_bar_horizontal_2

progress_bar_horizontal_3

progress_bar_horizontal_4

P.S. Se hai bisogno di una direzione inversa della barra di avanzamento, basta capovolgere i numeri nel nome delle immagini in progress_bar_indeterminate.xml.

Buona giornata! =)

+0

Si potrebbe desiderare gli elementi dell'animazione-lista come questa: , quindi le immagini verranno ripetute anziché allungate. –

0

Ho trovato una soluzione, un po 'simile alla spiegazione di cui sopra, ma non ha avuto origine da essa. Funziona alla grande!

Dire Di seguito la nostra 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> 

poi nel codice Java, effettuare le seguenti operazioni:

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

La limitazione con la soluzione precedente è che clipDrawable.getDrawable() funziona solo per API 23+, quindi sono stato costretto a implementare questa nuova soluzione come postata di seguito. Dovevo quindi creare manualmente un LayerDrawable per il mio ProgressBar. – prateek

0

download_progress_anim.xml codice

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

Spero che aiuti. Puoi facilmente modificarlo per supportare la tua implementazione.

Problemi correlati