在本文中,我们将带你了解android-ListAdapter任务不可能吗?将ImageViews和Animations结合在一起吗?在这篇文章中,我们将为您详细介绍android-ListAdapt
在本文中,我们将带你了解android-ListAdapter任务不可能吗?将ImageViews和Animations结合在一起吗?在这篇文章中,我们将为您详细介绍android-ListAdapter任务不可能吗?将ImageViews和Animations结合在一起吗?的方方面面,并解答android listview baseadapter常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的Android AdapterViewAnimator、Android AdapterViewAnimator控件、Android Animation 之 ViewAnimator\ViewFlipper、Android ImageView setImageBitmap 不显示图片。
本文目录一览:- android-ListAdapter任务不可能吗?将ImageViews和Animations结合在一起吗?(android listview baseadapter)
- Android AdapterViewAnimator
- Android AdapterViewAnimator控件
- Android Animation 之 ViewAnimator\ViewFlipper
- Android ImageView setImageBitmap 不显示图片
android-ListAdapter任务不可能吗?将ImageViews和Animations结合在一起吗?(android listview baseadapter)
我有一个列表适配器,其中图像加载有旋转进度动画,直到从网上获取它们为止.当我在listView中向下滚动时,似乎动画旋转了上一张图像…这是一个非常奇怪且令人讨厌的效果.唯一应该旋转的是进度动画.
我使用一个称为ImageLoader的类来异步netfetch图像:
final int stub_id=R.drawable.progress;
public void displayImage(String url, Activity activity, ImageView imageView,int size)
{
//Log.d("ImageLoader" , url);
this.size=size;
if(cache.containsKey(url)) {
//If this works, then why do the OLD images still spin??
imageView.clearanimation();
//imageView.setBackgroundDrawable(null);
//imageView.setimageDrawable(null);
imageView.setimageBitmap(cache.get(url));
}
else
{
rotation = AnimationUtils.loadAnimation(activity, R.drawable.progress);
rotation.setRepeatCount(Animation.INFINITE);
imageView.startAnimation(rotation);
queuePhoto(url, activity, imageView);
//imageView.setimageResource(stub_id);
//imageView.setBackgroundResource(stub_id);
}
Resources r = activity.getResources();
int dip = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, r.getdisplayMetrics());
LayoutParams layoutParams = imageView.getLayoutParams();
layoutParams.height = dip;
layoutParams.width = dip;
imageView.setLayoutParams(layoutParams);
}
现在您可能会问,queuePhoto是做什么的?这是动画开始的唯一其他地方.
//Used to display bitmap in the UI thread
class Bitmapdisplayer implements Runnable
{
Bitmap bitmap;
ImageView imageView;
public Bitmapdisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}
public void run()
{
if(bitmap!=null) {
imageView.clearanimation();
imageView.setimageBitmap(bitmap);
}
else {
imageView.clearanimation();
rotation = AnimationUtils.loadAnimation(context, R.drawable.progress);
rotation.setRepeatCount(Animation.INFINITE);
imageView.startAnimation(rotation);
//imageView.setimageResource(stub_id);
}
}
}
现在,我的列表适配器的getView的一部分:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if( convertView == null ){
vi = inflater.inflate(R.layout.trending_item, null);
holder=new ViewHolder();
holder.img1 = (ImageView) vi.findViewById(R.id.t_item_1);
holder.img2 = (ImageView) vi.findViewById(R.id.t_item_2);
holder.img3 = (ImageView) vi.findViewById(R.id.t_item_3);
vi.setTag(holder);
} else {
holder=(ViewHolder)vi.getTag();
}
JSONObject t1= ts.get(1);
if(t1 !=null) {
holder.img1.setTag(t1.getString("image_small"));
imageLoader.displayImage(t1.getString("image_small"), act, holder.img1,IMAGE_SIZE);
holder.img1.setTag(TAG_T t1.getString("id"));
holder.img1.setonClickListener(ocl);
} else {
holder.img1.setimageDrawable(null);
holder.img1.setBackgroundDrawable(null);
holder.img1.setTag(null);
holder.img1.setTag(TAG_T, null);
}
更新
我实现了JBM提出的解决方案,但是我无法使其工作,他建议在UI线程上运行.
public class RemoteImageView extends ImageView implements RemoteLoadListener {
final int stub_id=R.drawable.progress;
int size;
private HashMap<String, Bitmap> cache=new HashMap<String, Bitmap>();
Animation rotation;
private File cacheDir;
public RemoteImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public RemoteImageView(Context context, AttributeSet attrs) {
super(context, attrs);
//Make the background thead low priority. This way it will not affect the UI performance
photoLoaderThread.setPriority(Thread.norM_PRIORITY-1);
//Find the dir to save cached images
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),context.getString(R.string.app_name));
else
cacheDir=context.getCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
}
public RemoteImageView(Context context) {
super(context);
}
public void displayRemoteImage(String url, Activity activity, int size)
{
this.myUrl = url;
this.size=size;
Resources r = activity.getResources();
int dip = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, r.getdisplayMetrics());
LayoutParams layoutParams = this.getLayoutParams();
layoutParams.height = dip;
layoutParams.width = dip;
this.setLayoutParams(layoutParams);
if(cache.containsKey(url)) {
this.clearanimation();
setimageBitmap(cache.get(url));
}
else
{
rotation = AnimationUtils.loadAnimation(activity, R.drawable.progress);
rotation.setRepeatCount(Animation.INFINITE);
this.startAnimation(rotation);
queuePhoto(url, activity, this);
}
}
@Override
public void onl oadSuccess(String url, Bitmap bmp) {
if (url.equals(myUrl)) {
setimageBitmap(bmp);
} else {
/* the arrived bitmap is stale. do nothing. */
}
}
@Override
public void onl oadFail(String url) {
if (url.equals(myUrl)) {
setimageBitmap(((BitmapDrawable)getResources().getDrawable(stub_id)).getBitmap());
} else {
/* the Failed bitmap is stale. do nothing. */
}
}
String myUrl;
private void queuePhoto(String url, Activity activity, ImageView imageView)
{
//This ImageView may be used for other images before. So there may be some old tasks in the queue. We need to discard them.
photosQueue.Clean(imageView);
PhotoToLoad p=new PhotoToLoad(url, imageView);
synchronized(photosQueue.photosToLoad){
photosQueue.photosToLoad.push(p);
photosQueue.photosToLoad.notifyAll();
}
//start thread if it's not started yet
if(photoLoaderThread.getState()==Thread.State.NEW)
photoLoaderThread.start();
}
PhotosQueue photosQueue=new PhotosQueue();
public void stopThread()
{
photoLoaderThread.interrupt();
}
//stores list of photos to download
class PhotosQueue
{
private Stack<PhotoToLoad> photosToLoad=new Stack<PhotoToLoad>();
//removes all instances of this ImageView
public void Clean(ImageView image)
{
for(int j=0 ;j<photosToLoad.size();){
if(photosToLoad.get(j).imageView==image)
photosToLoad.remove(j);
else
++j;
}
}
}
//Task for the queue
private class PhotoToLoad
{
public String url;
public ImageView imageView;
public PhotoToLoad(String u, ImageView i){
url=u;
imageView=i;
}
}
class Photosloader extends Thread {
public void run() {
try {
while(true)
{
//thread waits until there are any images to load in the queue
if(photosQueue.photosToLoad.size()==0)
synchronized(photosQueue.photosToLoad){
photosQueue.photosToLoad.wait();
}
if(photosQueue.photosToLoad.size()!=0)
{
PhotoToLoad photoToLoad;
synchronized(photosQueue.photosToLoad){
photoToLoad=photosQueue.photosToLoad.pop();
}
Bitmap bmp=getBitmap(photoToLoad.url);
cache.put(photoToLoad.url, bmp);
Object tag=photoToLoad.imageView.getTag();
if(tag!=null && ((String)tag).equals(photoToLoad.url)){
Bitmapdisplayer bd=new Bitmapdisplayer(bmp, photoToLoad.imageView);
Activity a=(Activity)photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}
if(Thread.interrupted())
break;
}
} catch (InterruptedException e) {
//allow thread to exit
}
}
}
Photosloader photoLoaderThread=new Photosloader();
//Used to display bitmap in the UI thread
class Bitmapdisplayer implements Runnable
{
Bitmap bitmap;
ImageView imageView;
public Bitmapdisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}
public void run()
{
if(bitmap!=null) {
imageView.clearanimation();
imageView.setimageBitmap(bitmap);
}
else {
imageView.clearanimation();
imageView.setimageResource(stub_id);
}
}
}
private Bitmap getBitmap(String url)
{
System.out.println("GET: " +url);
if(url== null) {
return null;
}
//I identify images by hashcode. Not a perfect solution, good for the demo.
String filename=String.valueOf(url.hashCode());
File f=new File(cacheDir, filename);
//from SD cache
Bitmap b = decodeFile(f);
if(b!=null)
return b;
//from web
try {
Bitmap bitmap=null;
InputStream is=new URL(url).openStream();
OutputStream os = new FileOutputStream(f);
Utils.copyStream(is, os);
os.close();
bitmap = decodeFile(f);
return bitmap;
} catch (Exception ex){
ex.printstacktrace();
return null;
}
}
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//Find the correct scale value. It should be the power of 2.
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<size || height_tmp/2<size)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {
Log.d("ImageLoader",e.getMessage(),e);
}
return null;
}
}
解决方法:
这里的问题是ImageView与displayImage函数之间的竞争.当列表向上或向下滚动时,行将被重用,因此,当远程映像到达时,通常会发生其目标视图已经属于另一行的情况.唯一可靠的方法是让您拥有自己的类RemoteImageView来扩展ImageView,该ImageView可在内部处理图像.然后,RemoteImageView可以进行适当的同步.
让您的queuePhoto方法采用RemoteLoadListener代替ImageView,如下所示:
public interface RemoteLoadListener {
void onl oadFail(String url);
void onl oadSuccess(String url, Bitmap bmp);
}
然后将RemoteImageView设置为RemoteLoadListener并在内部执行所有操作:
public class RemoteImageView extends ImageView implements RemoteLoadListener {
final int static stub_id=R.drawable.progress;
public void displayImage(String url, Activity activity, int size)
{
myUrl = url;
if(cache.containsKey(url)) {
...
setimageBitmap(cache.get(url));
}
else
{
...
imageView.startAnimation(rotation);
queuePhoto(url, activity, this);
}
}
@Override
public void onl oadSuccess(String url, Bitmap bmp) {
if (url.equals(myUrl)) {
setimageBitmap(bmp);
} else {
/* the arrived bitmap is stale. do nothing. */
}
}
@Override
public void onl oadFail(String url) {
if (url.equals(myUrl)) {
setimageBitmap(placeholder);
} else {
/* the Failed bitmap is stale. do nothing. */
}
}
}
因此,在您的getView方法中,您只需执行以下操作:
holder.img1.displayImage(t1.getString("image_small"), act, IMAGE_SIZE);
更新
首先尝试降低系统的复杂性.我已经删除了您的照片队列和缓存,并将其替换为从Web上下载图像(此部分基于您的代码).我没有运行这段代码,只是输入了它.但这应该给您一个清晰的想法.
public class RemoteImageView extends ImageView implements RemoteLoadListener {
public RemoteImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RemoteImageView(Context context) {
super(context);
}
public void displayRemoteImage(String url, Activity activity, int size)
{
this.myUrl = url;
this.size=size;
Resources r = activity.getResources();
int dip = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, r.getdisplayMetrics());
LayoutParams layoutParams = this.getLayoutParams();
layoutParams.height = dip;
layoutParams.width = dip;
this.setLayoutParams(layoutParams);
{
rotation = AnimationUtils.loadAnimation(activity, R.drawable.progress);
rotation.setRepeatCount(Animation.INFINITE);
this.startAnimation(rotation);
queuePhoto(url, activity, this);
}
}
@Override
public void onl oadSuccess(String url, Bitmap bmp) {
if (url.equals(myUrl)) {
setimageBitmap(bmp);
} else {
/* the arrived bitmap is stale. do nothing. */
}
}
@Override
public void onl oadFail(String url) {
if (url.equals(myUrl)) {
setimageBitmap(((BitmapDrawable)getResources().getDrawable(stub_id)).getBitmap());
} else {
/* the Failed bitmap is stale. do nothing. */
}
}
String myUrl;
private void queuePhoto(final String url, final RemoteLoadListener listener)
{
new AsyncTask<Void, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(Void... params) {
//from web
Bitmap bitmap = null;
InputStream is = null;
OutputStream os = null;
try {
is = new URL(url).openStream();
os = new FileOutputStream(f);
Utils.copyStream(is, os);
bitmap = decodeFile(f);
} catch (Exception ex){
bitmap = null;
} finally {
if (is != null) try { is.close(); } catch (IOException e) { /* ignore */ };
if (os != null) try { os.close(); } catch (IOException e) { /* ignore */ };
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
if (result != null) {
listener.onLoadSuccess(url, result);
} else {
listener.onLoadFail(url);
}
};
}.execute();
}
}
PS:请注意尝试-在使用流时最终阻塞.
Android AdapterViewAnimator
public abstract class AdapterViewAnimator extends AdapterView<T extends Adapter>
java.lang.Object
↳ android.view.View
↳ android.view.ViewGroup
↳ android.widget.AdapterView<Textends android.widget.Adapter>
↳android.widget.AdapterViewAnimator
已知直接子类
- 相关方法
-
返回
- 用于提供视图内容的适配器.
-
返回
- 小部件顶端到文本基线的偏移量;或者是 -1 当小部件不支持基线对齐时.
-
返回
- 当前显示的视图.
-
参见
- getDisplayedChild()
-
返回
- 动画,当未设置时为空.
-
参见
- setInAnimation(android.animation.ObjectAnimator)
- setInAnimation(android.content.Context, int)
-
返回
- 动画,当未设置时为空.
-
参见
- setOutAnimation(android.animation.ObjectAnimator)
- setOutAnimation(android.content.Context, int)
-
返回
- 当前选中条目对应的视图;无选中条目时返回空.
- 参数
-
-
state 之前由 onSaveInstanceState() 返回的状态信息.
-
-
返回
- 返回包含视图当前状态的 Parcelable 对象,当不想保存状态时返回空.默认实现返回空.
- 参数
-
-
ev 动作时间
-
-
返回
- 如果处理了事件,返回真;否则返回假.
- 参数
-
-
adapter 用于创建视图内容的适配器.
-
- 参数
-
-
animate 视图动画对象首次显示时为当前视图显示动画时为真;否则为假.
-
- 参数
-
-
whichChild 要显示的子视图索引
-
- 参数
-
-
inAnimation 视图进入屏幕时启动的动画
-
-
参见
- getInAnimation()
- setInAnimation(android.content.Context, int)
- 参数
-
-
context 应用程序上下文 resourceID 动画的资源 ID
-
-
参见
- getInAnimation()
- setInAnimation(android.animation.ObjectAnimator)
- 参数
-
-
context 应用程序上下文 resourceID 动画的资源 ID
-
-
参见
- getOutAnimation()
- setOutAnimation(android.animation.ObjectAnimator)
- 参数
-
-
outAnimation 视图退出屏幕时启动的动画
-
-
参见
- getOutAnimation()
- setOutAnimation(android.content.Context, int)
- 参数
-
-
intent 用于标识适配器连接的 RemoteViewsService 的意图.
-
- 参数
-
-
position 选择的数据条目的索引(从零开始).
-
- 参数
-
-
changed 是否为视图设置了新的大小和位置. left 相对于父视图的左侧的位置. top 相对于父视图的顶部的位置. right 相对于父视图的右侧的位置. bottom 相对于父视图的底部的位置.
-
- 参数
-
-
widthMeasureSpec 父视图要求的横向空间大小.该要求由 View.MeasureSpec 进行了编码处理. heightMeasureSpec 父视图要求的纵向空间大小.该要求由 View.MeasureSpec 进行了编码处理.
-
AdapterViewFlipper, StackView
一:类概述:
AdapterViewAnimator继承自基类AdapterView,当在视图间切换时会显示动画.
二:xml属性:
android:animateFirstView
定义 ViewAnimation 首次显示时是否对当前视图应用动画.
一定是布尔值,“true”或“false”.
也可以是对包含该类型值的资源(形式为 “@[package:]type:name”)或主题属性(形式为 “?[package:][type:]name”) 的参照.
该属性与全局属性资源符号 animateFirstView 对应.
android:inAnimation
//标识显示视图时使用的动画.
//一定是对其它资源的参照,形式为“@[+][package:]type:name” 或“?[package:][type:]name”形式的主题属性.
//该属性与全局属性资源符号 inAnimation 对应.
//相关方法
android:loopViews
//定义当动画执行到列表尾部后,是否循环执行到第一个视图.
//一定是布尔值,“true”或“false”.
//也可以是对包含该类型值的资源(形式为 “@[package:]type:name”)或主题属性(形式为 “?[package:][type:]name”) 的参照.
//该属性与全局属性资源符号 loopViews 对应.
//相关方法
android:outAnimation
//标识隐藏视图时使用的动画.
//一定是对其它资源的参照,形式为“@[+][package:]type:name” 或“?[package:][type:]name”形式的主题属性.
//该属性与全局属性资源符号 outAnimation 对应.
//相关方法
三:公开的构造函数:
public AdapterViewAnimator ( Context context); //引入自: API 级别11
public AdapterViewAnimator ( Context context, AttributeSet attrs); // 引入自: API 级别11
public AdapterViewAnimator ( Context context, AttributeSet attrs, int defStyleAttr);
四:公共方法:
public void advance ();// 引入自: API 级别11
//由 AppWidgetHost 调用.在应用小部件中用于移动到下一个视图.
public void deferNotifyDataSetChanged (); // 引入自: API 级别14
//该设置推迟向没有连接的、未确定 RemoteViewsAdapter 发送 notifyDataSetChanged 消息.
public void fyiWillBeAdvancedByHostKThx ();// 引入自: API 级别11
//由 AppWidgetHost 调用.指出将来的某个时点,会调用 advance() 将AdapterViewAnimator 中的视图向前移动.这样子类可以执行一些必要的设置,比如停止自动移动他们的子视图.
public Adapter getAdapter () | 引入自: API 级别11 |
返回当前与该小部件关联的适配器.
public int getBaseline () | 引入自: API 级别11 |
返回小部件顶端到文本基线的偏移量.如果小部件不支持基线对齐,该方法返回 -1.
public View getCurrentView () | 引入自: API 级别11 |
返回当前显示的子视图.
public int getDisplayedChild () | 引入自: API 级别11 |
返回当前显示的子视图索引.
public ObjectAnimator getInAnimation () | 引入自: API 级别11 |
返回视图进入屏幕时显示的动画.
public ObjectAnimator getOutAnimation () | 引入自: API 级别11 |
返回视图退出屏幕时显示的动画.
public View getSelectedView () | 引入自: API 级别11 |
public boolean onRemoteAdapterConnected () | 引入自: API 级别11 |
适配器建立到 RemoteViewsService 的连接时的回调函数.
public void onRemoteAdapterDisconnected () | 引入自: API 级别11 |
适配器断开到 RemoteViewsService 的连接时的回调函数.
public void onRestoreInstanceState ( Parcelable state) | 引入自: API 级别11 |
允许视图重新应用之前由 onSaveInstanceState() 保存的内部状态的回调函数. 该方法得 state 参数不可能为空.
public Parcelable onSaveInstanceState () | 引入自: API 级别11 |
允许视图保存其内部状态的回调函数,以便于之后使用相同状态创建新实例. 该状态应该只包含非持久的或者之后不可重现的信息.例如,你不能保存视图在屏幕上的位置,因为在创建新视图时,会在视图得层次结构中重新计算它的位置.
这里是一些可以保存的信息的例子:文本框中当前光标的位置(通常不是文字内容本身,因为文字内容一般保存在内容提供者或其他持久的储存器中),列表视图中的当前选中条目等等.
public boolean onTouchEvent ( MotionEvent ev) | 引入自: API 级别11 |
实现该方法可以处理触屏动作事件.
public void setAdapter ( Adapter adapter) | 引入自: API 级别11 |
设置用于为该小部件的视图提供用于显示的数据的适配器.
public void setAnimateFirstView (boolean animate) | 引入自: API 级别11 |
设置视图动画对象首次显示时,是否为当前视图显示动画.
public void setDisplayedChild (int whichChild) | 引入自: API 级别11 |
设置显示那个子视图.
public void setInAnimation ( ObjectAnimator inAnimation) | 引入自: API 级别11 |
指定视图进入屏幕时显示的动画.
public void setInAnimation ( Context context, int resourceID) | 引入自: API 级别11 |
指定视图进入屏幕时显示的动画.
public void setOutAnimation ( Context context, int resourceID) | 引入自: API 级别11 |
指定视图退出屏幕时显示的动画.
public void setOutAnimation ( ObjectAnimator outAnimation) | 引入自: API 级别11 |
指定视图退出屏幕时显示的动画.
public void setRemoteViewsAdapter ( Intent intent) | 引入自: API 级别11 |
将 AdapterViewAnimator 设置为使用通过制定的意图连接的 RemoteViewsService 的远程视图适配器.
public void setSelection (int position) | 引入自: API 级别11 |
设置当前选择条目.为了支持无障碍功能,重写该方法的子类必须首先调用父类的该方法.
public void showNext () | 引入自: API 级别11 |
显示下一个子视图.
public void showPrevious () | 引入自: API 级别11 |
显示上一个子视图.
保护的方法
protected void onLayout (boolean changed, int left, int top, int right, int bottom) | 引入自: API 级别11 |
该视图设置其子视图的大小及位置时调用.派生类可以重写此方法,并为其子类布局.
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) | 引入自: API 级别11 |
评估视图及其内容,以决定其宽度和高度.此方法由 measure(int, int) 调用,子类可以重载以提供更精确、更有效率的衡量其内容尺寸的方法.
约定: 覆盖该方法时,必须调用 setMeasuredDimension(int, int) 方法来保存评估结果的视图的宽度和高度.如果忘记将导致 measure(int, int) 方法抛出IllegalStateException异常.要有效的利用父类的 onMeasure(int, int)方法.
基类测量的是背景的大小,除非 MeasureSpec 允许超过背景.子类应该重写 onMeasure(int, int) 方法,以为其内容提供更适合的大小.
如果重写了该方法,子类要确保其高度和宽度大于等于视图的最小高度和宽度. ( getSuggestedMinimumHeight() 和 getSuggestedMinimumWidth())
Android AdapterViewAnimator控件
AdapterViewAnimator(堆View),已知子类有AdapterViewFlipper, StackView,是一系列View的集合,这些View叠加一起,并且View之间可以进行切换,并且在多个View切换过程体现渐隐渐现的动画效果。通过AdapterViewAnimator.setAdapter()方法设置一组要显示的View,通过AdapterViewAnimator.showPrevious()方法移动到前一个View,通过AdapterViewAnimator.showNext()移动到下一个ViewAndroid Animation 之 ViewAnimator\ViewFlipper
选自 Android 3.0 Animations Beginners Guide Bring Your Android Applications To Lefe With Stunning Animations
动画 http://stackoverflow.com/questions/5151591/android-left-to-right-slide-animation
Viewpper 是一个为了翻页动画而封装的小类。它使用 tween 动画类,并将它们扩展到 xml 文件。
main.xml
ViewFlipper 有两个属性,android:inAnimation 和 android.outAnimation,可以设置进出动画
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ViewFlipper
android:id="@+id/pages"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/text_1_1" />
<ImageView
android:id="@+id/rollingball"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="60dp"
android:src="@drawable/ball"
android:contentDescription="@string/app_name" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/text_1_2" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/text_2_1" />
<ImageView
android:id="@+id/bouncingball"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="60dp"
android:src="@drawable/ball"
android:contentDescription="@string/app_name" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/text_2_2" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/text_3_1" />
</ViewFlipper>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center" >
<Button
android:id="@+id/prev"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableLeft="@android:drawable/ic_media_previous"
android:text="@string/button_prev" />
<Button
android:id="@+id/next"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableRight="@android:drawable/ic_media_next"
android:text="@string/button_next" />
</LinearLayout>
</LinearLayout>
slidein_to_left.xml //in from right to left used by next button
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator" >
<translate
android:duration="500"
android:fromXDelta="100%p"
android:toXDelta="0" />
</set>
slideout_to_left.xml //out from right to left used by next button
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator" >
<translate
android:duration="500"
android:fromXDelta="0"
android:toXDelta="-100%p" />
</set>
slidein_to_right.xml //in from left to right used by previous button
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator" >
<translate
android:duration="500"
android:fromXDelta="-100%p"
android:toXDelta="0" />
</set>
slideout_to_right.xml //out from left to right used by previous button
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator" >
<translate
android:duration="500"
android:fromXDelta="0"
android:toXDelta="100%p" />
</set>
MainActivity.java
package com.animation.interactivebook;
import android.os.Bundle;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
//import android.view.animation.AnimationUtils;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.ViewAnimator;
public class InteractiveBook extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final View rollingBall = findViewById(R.id.rollingball);
ObjectAnimator ballRoller = ObjectAnimator.ofFloat(rollingBall,
"TranslationX", 0, 400);
ballRoller.setDuration(2000);
ballRoller.setRepeatMode(ObjectAnimator.REVERSE);
ballRoller.setRepeatCount(ObjectAnimator.INFINITE);
ballRoller.start();
final View bouncingBall = findViewById(R.id.bouncingball);
ValueAnimator ballBouncer = ValueAnimator.ofInt(0, 40);
ValueAnimator.setFrameDelay(50);
ballBouncer
.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator ballBouncer) {
// We''ll fill this out in a minute
final int animatedValue = (Integer) ballBouncer
.getAnimatedValue();
bouncingBall.post(new Runnable() {
public void run() {
bouncingBall.setPadding(
bouncingBall.getPaddingLeft(),
40 - animatedValue,
bouncingBall.getPaddingRight(),
animatedValue);
bouncingBall.invalidate();
}
});
}
});
ballBouncer.setDuration(2000);
ballBouncer.setRepeatMode(ValueAnimator.REVERSE);
ballBouncer.setRepeatCount(ValueAnimator.INFINITE);
ballBouncer.start();
final AnimationSet slideinToLeft = new AnimationSet(true);
TranslateAnimation slide1 = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, 1f, Animation.RELATIVE_TO_PARENT,
0, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0);
ScaleAnimation scale1 = new ScaleAnimation(10, 1, 10, 1);
slideinToLeft.addAnimation(slide1);
slideinToLeft.addAnimation(scale1);
slideinToLeft.setDuration(1000);
final AnimationSet slideoutToLeft = new AnimationSet(true);
TranslateAnimation slide2 = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT,
-1f, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF,
0);
ScaleAnimation scale2 = new ScaleAnimation(1, 10, 1, 10);
slideoutToLeft.addAnimation(slide2);
slideoutToLeft.addAnimation(scale2);
slideoutToLeft.setDuration(1000);
final AnimationSet slideinToRight = new AnimationSet(true);
TranslateAnimation slide3 = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, -1f,
Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, 0);
ScaleAnimation scale3 = new ScaleAnimation(10, 1, 10, 1);
slideinToRight.addAnimation(slide3);
slideinToRight.addAnimation(scale3);
slideinToRight.setDuration(1000);
final AnimationSet slideoutToRight = new AnimationSet(true);
TranslateAnimation slide4 = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT,
1f, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF,
0);
ScaleAnimation scale4 = new ScaleAnimation(1, 10, 1, 10);
slideoutToRight.addAnimation(slide4);
slideoutToRight.addAnimation(scale4);
slideoutToRight.setDuration(1000);
final ViewAnimator pages = (ViewAnimator) findViewById(R.id.pages);
Button prev = (Button) findViewById(R.id.prev);
Button next = (Button) findViewById(R.id.next);
prev.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// pages.clearAnimation();
// Animation inAnimation =
// AnimationUtils.loadAnimation(InteractiveBook.this,
// R.anim.slidein_to_right);
// Animation outAnimation =
// AnimationUtils.loadAnimation(InteractiveBook.this,
// R.anim.slideout_to_right);
// pages.setInAnimation(inAnimation);
// pages.setOutAnimation(outAnimation);
pages.clearAnimation();
pages.setInAnimation(slideinToRight);
pages.setOutAnimation(slideoutToRight);
pages.showPrevious();
}
});
next.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// pages.clearAnimation();
// Animation inAnimation =
// AnimationUtils.loadAnimation(InteractiveBook.this,
// R.anim.slidein_to_left);
// Animation outAnimation =
// AnimationUtils.loadAnimation(InteractiveBook.this,
// R.anim.slideout_to_left);
// pages.setInAnimation(inAnimation);
// pages.setOutAnimation(outAnimation);
pages.clearAnimation();
pages.setInAnimation(slideinToLeft);
pages.setOutAnimation(slideoutToLeft);
pages.showNext();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.interactive_book, menu);
return true;
}
}
Android ImageView setImageBitmap 不显示图片
从sd卡里读出图片后有时调用setImageBitmap(bitmap)方法会显示不出图片,仔细考虑过后原来是加载的图片过大导致的,解决办法为:
BitmapFactory.Options op = new BitmapFactory.Options();
op.inSampleSize = 2;
//op.inJustDecodeBounds = true; //它仅仅会把它的宽,高取回来给你,这样就不会占用太多的内存,也就不会那么频繁的发生OOM了。
//op.inPreferredConfig = Bitmap.Config.ARGB_4444; // 默认是Bitmap.Config.ARGB_8888
private Bitmap createBitmapFromByteData(byte[] data ,Options options){
Bitmap bitmap = null;
if(options == null){
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
}else{
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
}
return bitmap;
}
这样返回的bitmap就可以被显示出来了。
今天关于android-ListAdapter任务不可能吗?将ImageViews和Animations结合在一起吗?和android listview baseadapter的分享就到这里,希望大家有所收获,若想了解更多关于Android AdapterViewAnimator、Android AdapterViewAnimator控件、Android Animation 之 ViewAnimator\ViewFlipper、Android ImageView setImageBitmap 不显示图片等相关知识,可以在本站进行查询。
本文标签: