在每一个列表视图项纺纱进度条(Spinning progress bar in every list

2019-07-30 01:25发布

我一直在抓我的头在这个很长一段时间,并寻找没有任何的运气一个答案! 这似乎是微不足道的,但据我所知,事实并非如此。

我用一个ListView在我的Android应用程序,其中加载和显示的内容之前,每个项目(视图)显示纺纱进度(内容是通过HTTP调用和JSON检索,所以它可能需要一段时间来处理)。 问题是,纺纱进度条相互独立的转动,从而创造一个扑朔迷离的混乱,而不是好看的标记加载一个syncronised行的效果。

我用尽了一切我能想出......不可回收的getView()的进度......具有相同的进度只有一个实例...重置ProgressBars安卓进步每当列表项获得可见的(通过onScroll ()在活动)...等,但由于它们在开始创建的时候(当getView被调用的适配器)旋转,他们将永远不会有相同的周期同步。

任何建议,欢迎!

Answer 1:

编辑:现在完美的作品! - 插入动画监听通话setStartOffset()返回到0的第一重复之后,使其不留“跳”随机。


我发现这个问题,它的工作原理是动画定时到当前系统毫秒的工作方案。 这是一个黑客攻击的一位,因为它使用反射来获取mAnimation现场ProgressBar 。 话虽这么说,这个领域已经在Android源留在地方,因为它创建(对于高至4.2)。

创建android.widget.SyncedProgressBar类,并用它代替ProgressBar在您的.xml文件。 它在本质上使得在动画区间的开头动画开始。 您也可以玩弄setDuration(500)以确认它可以工作(进度轮将真正快速旋转)。 希望这可以帮助!

package android.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;

import java.lang.reflect.Field;

/**
* @author Oleg Vaskevich
*
*/
public class SyncedProgressBar extends ProgressBar {

    public SyncedProgressBar(Context context) {
        super(context);
        modifyAnimation();
    }

    public SyncedProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        modifyAnimation();
    }

    public SyncedProgressBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        modifyAnimation();
    }

    @Override
    public void setVisibility(int v) {
        super.setVisibility(v);
        modifyAnimation();
    }

    @SuppressLint("NewApi")
    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        modifyAnimation();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        modifyAnimation();
    }

    @Override
    public synchronized void setIndeterminate(boolean indeterminate) {
        super.setIndeterminate(indeterminate);
        modifyAnimation();
    }

    public void modifyAnimation() {
        Field mAnim;
        try {
            mAnim = ProgressBar.class.getDeclaredField("mAnimation");
            mAnim.setAccessible(true);
            AlphaAnimation anim = (AlphaAnimation) mAnim.get(this);
            if (anim == null)
                return;

            // set offset to that animations start at same time
            long duration = anim.getDuration();
            long timeOffset = System.currentTimeMillis() % duration;
            anim.setDuration(duration);
            anim.setStartOffset(-timeOffset);
            anim.setAnimationListener(new AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                    animation.setStartOffset(0);
                }

                @Override
                public void onAnimationEnd(Animation animation) {
                }
            });
        } catch (Exception e) {
            Log.d("SPB", "that didn't work out...", e);
            return;
        }
        postInvalidate();
    }

}


Answer 2:

以下是如何使它发挥作用。 只使用一个AnimationDrawable,复回调。 进度并没有真正添加任何东西,你可能也与View坚持。 请查看的子类,绕过绘制对象管理。

public class Whirly extends View
{
   Drawable image = null;

   public Whirly(Context context, AttributeSet attr)
   {
      super(context, attr);
   }

   @Override
   public void draw(Canvas canvas)
   {
      if (image!=null)
         image.draw(canvas);
   }

   public void setImageDrawable(Drawable image)
   {
      this.image = image;
      invalidate();
   }
}

然后让所有的whirlies你的活动跟踪莫名其妙。

public class Demo extends Activity implements Drawable.Callback
{
   private Handler h;
   private AnimationDrawable a;

   private Whirly w0;
   private Whirly w1;
   private Whirly w2;
   private Whirly w3;

   public void onCreate(Bundle bundle)
   {
      ...

      h = new Handler();

      a = (AnimationDrawable) getResources().getDrawable(R.drawable.mywhirly);
      int width = a.getIntrinsicWidth();
      int height = a.getIntrinsicHeight();
      a.setBounds(0, 0, width, height);

      w0 = (Whirly) findViewById(R.id.whirly0);
      w1 = (Whirly) findViewById(R.id.whirly1);
      w2 = (Whirly) findViewById(R.id.whirly2);
      w3 = (Whirly) findViewById(R.id.whirly3);

      w0.setImageDrawable(a);
      w1.setImageDrawable(a);
      w2.setImageDrawable(a);
      w3.setImageDrawable(a);

      a.setCallback(this);
      a.start();
   }

   public void invalidateDrawable (Drawable who)
   {
      w0.invalidate();
      w1.invalidate();
      w2.invalidate();
      w3.invalidate();
   }

   public void scheduleDrawable (Drawable who, Runnable what, long when)
   {
      h.postAtTime(what, who, when);
   }

   public void unscheduleDrawable (Drawable who, Runnable what)
   {
      h.removeCallbacks(what, who);
   }
}


Answer 3:

在您的适配器getView()禁用progressViwe的,然后每个progressView

handler.postAtTime(new Runnable(){

public void run(){
     progressView.setEnabled(true);
}}, someTimeInTheFuture
);

这将完成是使在同一时间所有progressViews。 这可能会实现,我没有测试过。 如果不工作,那么你可能要添加动态的progressView(不包括在布局,但通过添加addView())。 但是这样做的可运行的,这里的关键是让他们都在同一时间得到补充。



Answer 4:

通过源代码,我看到旋转图像是因为私人的纺绘制挖掘Animation 。 有没有办法获得视图或动画,从而丢弃任何想法,我对所有的意见重用一个动画。 我说你唯一的选择是什么Jug6ernaut建议,即使它不是解决方案的最漂亮的。



Answer 5:

我不知道这是可能因为在你的每一行ListView当它移动关闭屏幕被回收。 当新的一行出现在屏幕上的ProgressBar意见,将所有必须彼此重新同步。 保持所有行的同步将是一个很大的PITA。

你有没有考虑加载的所有列表数据的一个请求和缓存数据本地存储? 这将是更有效,产生更好的用户体验。 这不是非常有用的一个ListView与空行立即加载。 我宁愿等待名单完全填充。



Answer 6:

1>列表行创建布局

<RelativeLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="10dip" >

    <TextView
        android:id="@+id/word_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:text="Word 1" />

    <ProgressBar
        android:id="@+id/row_progress"
        style="@style/Widget.Sherlock.Light.ProgressBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:indeterminate="true" />

    <ImageView
        android:id="@+id/speaker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:src="@drawable/speaker_icon" 
        android:visibility="gone"/>
</RelativeLayout>

2>然后在getView方法

if(word.getIsWordSynchedLocally() == 1){
                convertView.findViewById(R.id.row_progress).setVisibility(View.GONE);
                convertView.findViewById(R.id.speaker).setVisibility(View.VISIBLE);
            }else{
                convertView.findViewById(R.id.row_progress).setVisibility(View.VISIBLE);
                convertView.findViewById(R.id.speaker).setVisibility(View.GONE);
            }


文章来源: Spinning progress bar in every listview item