2014-12-07 80 views
0

我已经创建了基本适配器并将动画应用到图像视图,该图像视图是每3秒后自定义布局的一部分。每行都有图像数组,所以我试图淡出当前图像和时尚 - 在新的一个。我已创建处理程序与runnable计时器在活动中,每3秒后调用adapter.notifyDataSetChanged()。如果不应用动画,我的适配器将如下所示:Android BaseAdapter动画图像查看器

public class FerrariAdapter extends BaseAdapter { 

/* 
* Variable Declaration Part 
*/ 

private Context mContext; 
private ArrayList<String> mTitle, mOwner, mDate; 
private HashMap<String, ArrayList<String>> mImages; 
private HashMap<Integer, Integer> mLastImagePosition; 
private ViewHolder mHolder; 
private boolean is_animation = false; 
private Animation mFadeIn, mFadeOut; 

/* Constructor that initialize variables getting from activity */ 

public FerrariAdapter(Context mContext, ArrayList<String> mTitle, 
     ArrayList<String> mOwner, ArrayList<String> mDate, 
     HashMap<String, ArrayList<String>> mImages, 
     HashMap<Integer, Integer> mLastImagePosition) { 

    this.mContext = mContext; 
    this.mTitle = mTitle; 
    this.mOwner = mOwner; 
    this.mDate = mDate; 
    this.mImages = mImages; 
    this.mLastImagePosition = mLastImagePosition; 
    mFadeOut = AnimationUtils.loadAnimation(mContext, R.anim.anim_fadeout); 
    mFadeIn = AnimationUtils.loadAnimation(mContext, R.anim.anim_fadein); 

} 

@Override 
public int getCount() { 
    // TODO Auto-generated method stub 
    return mTitle.size(); 
} 

@Override 
public Object getItem(int position) { 
    // TODO Auto-generated method stub 
    return mTitle.get(position); 
} 

@Override 
public long getItemId(int position) { 
    // TODO Auto-generated method stub 
    return 0; 
} 

@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    // TODO Auto-generated method stub 
    View mView = convertView; 
    if (mView == null) { 

     /* 
     * Inflating custom layout and getting components IDs to set each 
     * row of ListView 
     */ 

     mView = LayoutInflater.from(mContext).inflate(R.layout.car_tile, 
       null); 
     mHolder = new ViewHolder(); 
     mHolder.mTitleHolder = (TextView) mView 
       .findViewById(R.id.titleHolder); 
     mHolder.mOwnerHolder = (TextView) mView 
       .findViewById(R.id.OwnerHolder); 
     mHolder.mDateHolder = (TextView) mView 
       .findViewById(R.id.dateHolder); 
     mHolder.mImageHolder = (ImageView) mView 
       .findViewById(R.id.imageHolder); 

     mView.setTag(mHolder); 
    } else { 
     mHolder = (ViewHolder) mView.getTag(); 
    } 

    /* Set Value to each row */ 

    mHolder.mTitleHolder.setText(mTitle.get(position)); 
    mHolder.mOwnerHolder.setText(mOwner.get(position)); 
    mHolder.mDateHolder.setText(Utils.millisToDate(
      Long.parseLong(mDate.get(position)), "dd MMM yyyy HH:mm")); 

    mHolder.mImageHolder.setImageBitmap(getImagefromHashmap(position)); 
    /*mFadeOut.setAnimationListener(new AnimationListener() { 

     @Override 
     public void onAnimationStart(Animation animation) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void onAnimationRepeat(Animation animation) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void onAnimationEnd(Animation animation) { 
      // TODO Auto-generated method stub 

     } 
    }); 
    mHolder.mImageHolder.setAnimation(mFadeOut);*/ 

    return mView; 
} 

/* 
* This class is used to hold position of each component so it shouln't be 
* repeat again and again 
*/ 

class ViewHolder { 

    ImageView mImageHolder; 
    TextView mTitleHolder, mOwnerHolder, mDateHolder; 

} 

private Bitmap getImagefromHashmap(int position) { 

    Bitmap mBitmap = null; 
    ArrayList<String> mImagesList = mImages.get(mTitle.get(position)); 
    int mLastImagePostion = mLastImagePosition.get(position); 

    if (mImagesList.size() - 1 > mLastImagePostion) { 

     mLastImagePostion++; 
     mLastImagePosition.put(position, mLastImagePostion); 

    } else { 

     mLastImagePostion = 0; 
     mLastImagePosition.put(position, mLastImagePostion); 

    } 

    String mImageName = mImagesList.get(mLastImagePostion); 
    // Get the AssetManager 
    AssetManager manager = mContext.getAssets(); 

    // Read a Bitmap from Assets 
    try { 
     InputStream mOpen = manager.open(mImageName); 
     mBitmap = BitmapFactory.decodeStream(mOpen); 

    } catch (Exception e) { 

    } 

    return Utils.resize(mBitmap, 
      (int) (Utils.getDeviceWidth(mContext)/2.5), 
      Utils.getDeviceHeight(mContext)/5); 

} 
} 

而且它通过将图像更改为imageview与每行都工作良好。现在,当我要在getview()上应用动画时,只有最后一行受到影响。所以我认为getView()在每行的动画完成之前调用。在应用动画时:

public class FerrariAdapter extends BaseAdapter { 

/* 
* Variable Declaration Part 
*/ 

private Context mContext; 
private ArrayList<String> mTitle, mOwner, mDate; 
private HashMap<String, ArrayList<String>> mImages; 
private HashMap<Integer, Integer> mLastImagePosition; 
private ViewHolder mHolder; 
private boolean is_animation = false; 
private Animation mFadeIn, mFadeOut; 

/* Constructor that initialize variables getting from activity */ 

public FerrariAdapter(Context mContext, ArrayList<String> mTitle, 
     ArrayList<String> mOwner, ArrayList<String> mDate, 
     HashMap<String, ArrayList<String>> mImages, 
     HashMap<Integer, Integer> mLastImagePosition) { 

    this.mContext = mContext; 
    this.mTitle = mTitle; 
    this.mOwner = mOwner; 
    this.mDate = mDate; 
    this.mImages = mImages; 
    this.mLastImagePosition = mLastImagePosition; 
    mFadeOut = AnimationUtils.loadAnimation(mContext, R.anim.anim_fadeout); 
    mFadeIn = AnimationUtils.loadAnimation(mContext, R.anim.anim_fadein); 

} 

@Override 
public int getCount() { 
    // TODO Auto-generated method stub 
    return mTitle.size(); 
} 

@Override 
public Object getItem(int position) { 
    // TODO Auto-generated method stub 
    return mTitle.get(position); 
} 

@Override 
public long getItemId(int position) { 
    // TODO Auto-generated method stub 
    return 0; 
} 

@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    // TODO Auto-generated method stub 
    View mView = convertView; 
    if (mView == null) { 

     /* 
     * Inflating custom layout and getting components IDs to set each 
     * row of ListView 
     */ 

     mView = LayoutInflater.from(mContext).inflate(R.layout.car_tile, 
       null); 
     mHolder = new ViewHolder(); 
     mHolder.mTitleHolder = (TextView) mView 
       .findViewById(R.id.titleHolder); 
     mHolder.mOwnerHolder = (TextView) mView 
       .findViewById(R.id.OwnerHolder); 
     mHolder.mDateHolder = (TextView) mView 
       .findViewById(R.id.dateHolder); 
     mHolder.mImageHolder = (ImageView) mView 
       .findViewById(R.id.imageHolder); 

     mView.setTag(mHolder); 
    } else { 
     mHolder = (ViewHolder) mView.getTag(); 
    } 

    /* Set Value to each row */ 

    mHolder.mTitleHolder.setText(mTitle.get(position)); 
    mHolder.mOwnerHolder.setText(mOwner.get(position)); 
    mHolder.mDateHolder.setText(Utils.millisToDate(
      Long.parseLong(mDate.get(position)), "dd MMM yyyy HH:mm")); 


    mFadeOut.setAnimationListener(new AnimationListener() { 

     @Override 
     public void onAnimationStart(Animation animation) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void onAnimationRepeat(Animation animation) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void onAnimationEnd(Animation animation) { 
      // TODO Auto-generated method stub 

      mHolder.mImageHolder.setImageBitmap(getImagefromHashmap(position)); 
     } 
    }); 
    mHolder.mImageHolder.setAnimation(mFadeOut); 

    return mView; 
} 

/* 
* This class is used to hold position of each component so it shouln't be 
* repeat again and again 
*/ 

class ViewHolder { 

    ImageView mImageHolder; 
    TextView mTitleHolder, mOwnerHolder, mDateHolder; 

} 

private Bitmap getImagefromHashmap(int position) { 

    Bitmap mBitmap = null; 
    ArrayList<String> mImagesList = mImages.get(mTitle.get(position)); 
    int mLastImagePostion = mLastImagePosition.get(position); 

    if (mImagesList.size() - 1 > mLastImagePostion) { 

     mLastImagePostion++; 
     mLastImagePosition.put(position, mLastImagePostion); 

    } else { 

     mLastImagePostion = 0; 
     mLastImagePosition.put(position, mLastImagePostion); 

    } 

    String mImageName = mImagesList.get(mLastImagePostion); 
    // Get the AssetManager 
    AssetManager manager = mContext.getAssets(); 

    // Read a Bitmap from Assets 
    try { 
     InputStream mOpen = manager.open(mImageName); 
     mBitmap = BitmapFactory.decodeStream(mOpen); 

    } catch (Exception e) { 

    } 

    return Utils.resize(mBitmap, 
      (int) (Utils.getDeviceWidth(mContext)/2.5), 
      Utils.getDeviceHeight(mContext)/5); 

} 
} 

那么如何处理这种情况,或者如何在每行完成动画后调用getView()?

感谢,

回答

0

如何:

  • 创建您的适配器处理程序,他们的工作将是运行的Runnable。
  • 每个Runnable实例将负责您列表中一个当前可见的行,每3秒将图像淡入淡出。
  • 每次调用getView时,为该行构造一个新的Runnable,并调用myHandler.postDelayed(runnable,3000)来启动淡化定时器。
  • 在ViewHolder中保留Runnable,并且在调用getView以回收行时,调用myHandler.removeCallbacks(runnable)以停止正在回收的视图上的3秒计时器。
  • 在Runnable的代码中,运行动画以将旧图像和新图像淡入。动画启动后,让Runnable将自身贴到处理程序,延迟时间相同。您可能需要一个Runnable子类,以便可以跟踪下一张要显示的图像。

这有道理吗?你需要我更多地解释它的任何部分吗?你需要看代码吗?

编辑:

这是我想到的一些代码。毫无疑问,我错过了一些作品,但我希望你明白。主要的重点是为每一行分别设置计时器,将图像动画化。我同意dor506,你需要每个动画中的一个以上。在此解决方案中,您每次都会加载动画的新实例,以便您可以听取它们的完成情况。

// construct the handler inside your adapter's constructor so you know it is on the UI thread 
    Handler myHandler = new Handler(); 

class FadeRunnable implements Runnable { 
    ImageView iv; 
    int position; 

    public FadeRunnable(ImageView iv, int position) { 
     this.iv = iv; 
     this.position = position; 
    } 

    @Override 
    public void run() { 
     Animation fadeOut = AnimationUtils.loadAnimation(mContext, R.anim.anim_fadeout); 
     fadeOut.setAnimationListener(new Animation.AnimationListener() { 
      @Override 
      public void onAnimationStart(Animation animation) { 
      } 

      @Override 
      public void onAnimationEnd(Animation animation) { 
       iv.setImageBitmap(getImagefromHashmap(position)); 
       Animation fadeIn = AnimationUtils.loadAnimation(mContext, R.anim.anim_fadein); 
       iv.startAnimation(fadeIn); 
      } 

      @Override 
      public void onAnimationRepeat(Animation animation) { 
      } 
     }); 
     iv.startAnimation(fadeOut); 
    } 
} 

/* 
* This class is used to hold position of each component so it shouln't be 
* repeat again and again 
*/ 
class ViewHolder { 

    ImageView mImageHolder; 
    TextView mTitleHolder, mOwnerHolder, mDateHolder; 
    FadeRunnable mRunnable; 

} 

@SuppressWarnings("deprecation") 
@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    View mView = convertView; 
    if (mView == null) { 
     mView = LayoutInflater.from(mContext).inflate(R.layout.car_tile, 
       null); 
     mHolder = new ViewHolder(); 
     mHolder.mTitleHolder = (TextView) mView 
       .findViewById(R.id.titleHolder); 
     mHolder.mOwnerHolder = (TextView) mView 
       .findViewById(R.id.OwnerHolder); 
     mHolder.mDateHolder = (TextView) mView 
       .findViewById(R.id.dateHolder); 
     mHolder.mImageHolder = (ImageView) mView 
       .findViewById(R.id.imageHolder); 

     mHolder.mRunnable = new FadeRunnable(mHolder.mImageHolder, position); 

     mView.setTag(mHolder); 
    } else { 
     mHolder = (ViewHolder) mView.getTag(); 
     myHandler.removeCallbacks(mHolder.mRunnable); 
    } 

/* Set Value to each row */ 
    mHolder.mTitleHolder.setText(mTitle.get(position)); 
    mHolder.mOwnerHolder.setText(mOwner.get(position)); 
    mHolder.mDateHolder.setText(Utils.millisToDate(
      Long.parseLong(mDate.get(position)), "dd MMM yyyy HH:mm")); 
    mHolder.mImageHolder.setImageBitmap(getImagefromHashmap(position)); 

    myHandler.postDelayed(mHolder.mRunnable, 3000); 

    return mView; 
} 

两件事情我没有做:

1)我没有写那将自身重新站上处理程序下一个图像了Runnable内的部分。你可以在第一个监听器中编写另一个监听器,或者你可以使FadeRunnable实现AnimationListener本身,并跟踪它是否正在消失,并做正确的事情。

2)这个解决方案可能需要的一件事,但我不想现在尝试编写它,是你可能需要取消一个在一行上运行的runnable,如果该行被回收并且另一个runnable想要开始淡入一个不同的动画。如果3秒定时器还没有关闭,它将工作正常,但如果它已经存在,并且现在旧的可运行的动画正在做动画,那么这可能是一个问题。

+0

是的,它可能有帮助。但仍然如果你可以为你的步骤编写代码,这对我会有帮助,因为做了太多的事情后,我卡住了:)。谢谢, – Jai 2014-12-07 08:18:20

+0

好吧,这将需要几分钟... – Bruce 2014-12-07 08:21:36

+0

非常感谢。等候!! – Jai 2014-12-07 08:22:12

0

你不能只用一个动画对象(mFadeOut)做到这一点。
调用mFadeOut.setAnimationListener(...)将导致最后一个视图(从getView返回)接收回调(onAnimationEnd)。 您应该先将mFadeOut对象转换为ArrayList或类似的东西,这样您可以支持多个动画(回调),或者使mFadeOut对象成为getView方法的本地对象。

+0

好主意。但是你确定它能正常工作吗?因为用3秒getview很快打电话 – Jai 2014-12-07 08:16:05

0

我认为他的主要问题是mFadeOut总是在视图的相同引用上运行,所以基本上你每次都重新启动动画,当然它只会在最后一项中显示。