一.Android官网上training的这个实例项目 com.example.android.animationsdemo.MainActivity

里面有5种4.0以上的实例效果

1.Simple Crossfade

这是一个文字从无到有逐渐显现的效果,没什么说的,就是一个函数

private void showContentOrLoadingIndicator(boolean contentLoaded) {        // Decide which view to hide and which to show.        final View showView = contentLoaded ? mContentView : mLoadingView;        final View hideView = contentLoaded ? mLoadingView : mContentView;        // Set the "show" view to 0% opacity but visible, so that it is visible        // (but fully transparent) during the animation.        showView.setAlpha(0f);        showView.setVisibility(View.VISIBLE);        // Animate the "show" view to 100% opacity, and clear any animation listener set on        // the view. Remember that listeners are not limited to the specific animation        // describes in the chained method calls. Listeners are set on the        // ViewPropertyAnimator object for the view, which persists across several        // animations.        showView.animate()                .alpha(1f)                .setDuration(mShortAnimationDuration)                .setListener(null);        // Animate the "hide" view to 0% opacity. After the animation ends, set its visibility        // to GONE as an optimization step (it won't participate in layout passes, etc.)        hideView.animate()                .alpha(0f)                .setDuration(mShortAnimationDuration)                .setListener(new AnimatorListenerAdapter() {                    @Override                    public void onAnimationEnd(Animator animation) {                        hideView.setVisibility(View.GONE);                    }                });    }

2.Card Flip

point 2.1

在android 3.0以上,你必须调用invalidateOptionsMenu() 当你要update你的menu时,因为action bar是一直出现的。

point 2.2

public abstractFragmentTransactionsetCustomAnimations(int enter, int exit, int popEnter, int popExit)

Since: API Level 13

Set specific animation resources to run for the fragments that are entering and exiting in this transaction. ThepopEnterandpopExitanimations will be played for enter/exit operations specifically when popping the back stack.

这是一个卡片翻转正背面切换的效果,做的其实一般。
if (savedInstanceState == null) {            // If there is no saved instance state, add a fragment representing the            // front of the card to this activity. If there is saved instance state,            // this fragment will have already been added to the activity.            getFragmentManager()                    .beginTransaction()                    .add(R.id.container, new CardFrontFragment())                    .commit();        } else {            mShowingBack = (getFragmentManager().getBackStackEntryCount() > 0);        }        // Monitor back stack changes to ensure the action bar shows the appropriate        // button (either "photo" or "info").        getFragmentManager().addOnBackStackChangedListener(this);

主要还是这个函数,它和onBackStackChanged(), popBackStack()配合,这一点值得学习。
private void flipCard() {        if (mShowingBack) {            getFragmentManager().popBackStack();            return;        }        // Flip to the back.        mShowingBack = true;        // Create and commit a new fragment transaction that adds the fragment for the back of        // the card, uses custom animations, and is part of the fragment manager's back stack.        getFragmentManager()                .beginTransaction()                .setCustomAnimations(                        R.animator.card_flip_right_in, R.animator.card_flip_right_out,                        R.animator.card_flip_left_in, R.animator.card_flip_left_out)                // Replace any fragments currently in the container view with a fragment                .replace(R.id.container, new CardBackFragment())                // Add this transaction to the back stack, allowing users to press Back                // to get to the front of the card.                .addToBackStack(null)                // Commit the transaction.                .commit();        // Defer an invalidation of the options menu (on modern devices, the action bar). This        // can't be done immediately because the transaction may not yet be committed. Commits        // are asynchronous in that they are posted to the main thread's message loop.        mHandler.post(new Runnable() {            @Override            public void run() {                invalidateOptionsMenu();            }        });    }

@Override    public void onBackStackChanged() {        mShowingBack = (getFragmentManager().getBackStackEntryCount() > 0);        // When the back stack changes, invalidate the options menu (action bar).        invalidateOptionsMenu();    }

3.Screen Slide

这个我用过很多次了,复习一遍。

<android.support.v4.view.ViewPager />

private ViewPager mPager;

private PagerAdapter mPagerAdapter;

// Instantiate a ViewPager and a PagerAdapter.        mPager = (ViewPager) findViewById(R.id.pager);        mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager());        mPager.setAdapter(mPagerAdapter);        mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {            @Override            public void onPageSelected(int position) {                // 更新actionbar的menu,可以借鉴                invalidateOptionsMenu();            }        });

@Override    public boolean onCreateOptionsMenu(Menu menu) {        super.onCreateOptionsMenu(menu);        getMenuInflater().inflate(R.menu.activity_screen_slide, menu);        menu.findItem(R.id.action_previous).setEnabled(mPager.getCurrentItem() > 0);        // 这个很好,我一般就只用上面的,没想到这里还可以这样写        MenuItem item = menu.add(Menu.NONE, R.id.action_next, Menu.NONE,                (mPager.getCurrentItem() == mPagerAdapter.getCount() - 1)                        ? R.string.action_finish                        : R.string.action_next);        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);        return true;    }
顺便把这个也贴上吧,要不感觉不完整

@Override    public boolean onOptionsItemSelected(MenuItem item) {        switch (item.getItemId()) {            case android.R.id.home:                // Navigate "up" the demo structure to the launchpad activity.                // See http://developer.android.com/design/patterns/navigation.html for more.                NavUtils.navigateUpTo(this, new Intent(this, MainActivity.class));                return true;            case R.id.action_previous:                // Go to the previous step in the wizard. If there is no previous step,                // setCurrentItem will do nothing.                mPager.setCurrentItem(mPager.getCurrentItem() - 1);                return true;            case R.id.action_next:                // Advance to the next step in the wizard. If there is no next step, setCurrentItem                // will do nothing.                mPager.setCurrentItem(mPager.getCurrentItem() + 1);                return true;        }        return super.onOptionsItemSelected(item);    }

最后,在加上继承的FragmentStatePagerAdapter 就好了,里面判断并创建显示的 Fragment。

这个create()方法比较有趣,一般都命名为getInstance(),可以看到 fragment传参的是 setArguments() 和 getArguments();

public static ScreenSlidePageFragment create(int pageNumber) {        ScreenSlidePageFragment fragment = new ScreenSlidePageFragment();        Bundle args = new Bundle();        args.putInt(ARG_PAGE, pageNumber);        fragment.setArguments(args);        return fragment;    }    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mPageNumber = getArguments().getInt(ARG_PAGE);    }


另外,再加一点,在Strings.xml中,
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"><string name="title_template_step">Step <xliff:g id="step_number">%1$d</xliff:g>: Lorem Ipsum</string>


 // Set the title view to show the page number.        ((TextView) rootView.findViewById(android.R.id.text1)).setText(                getString(R.string.title_template_step, mPageNumber + 1))

1、xliff:g标签介绍:
xliff:g标签是用于在动态的设置某些值时,需要进行字符串连接,但又不改变在其中的静态的字符常量的值,我们就需要使用此标签。

2、属性介绍
属性id可以随便命名
属性example表示举例说明,可以省略
%n$ms:代表输出的是字符串,n代表是第几个参数,设置m的值可以在输出之前放置空格
%n$md:代表输出的是整数,n代表是第几个参数,设置m的值可以在输出之前放置空格,也可以设为0m,在输出之前放置m个0
%n$mf:代表输出的是浮点数,n代表是第几个参数,设置m的值可以控制小数位数,如m=2.2时,输出格式为00.00

再举个例子:
<string name="time">当前时间:<xliff:g id="prefix">%1$s</xliff:g>时 <xliff:g id="time">%2$s</xliff:g>分</string>//然后通过程序,context.getString(R.string.time,"10","05");
将会输出——当前时间:10时05分


4.Zoom

其中包含了很多数学,Yay, Math.

其主要就是一个ImageView到另一个ImageView的比例,距离计算,和动画的设计。

AnimatorSet set = new AnimatorSet();        set           .play(ObjectAnimator.ofFloat(expandedImageView, View.X, startBounds.left,                        finalBounds.left))            .with(ObjectAnimator.ofFloat(expandedImageView, View.Y, startBounds.top,                        finalBounds.top))            .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X, startScale, 1f))            .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y, startScale, 1f));        set.setDuration(mShortAnimationDuration);        set.setInterpolator(new DecelerateInterpolator());        set.addListener(new AnimatorListenerAdapter() {            @Override            public void onAnimationEnd(Animator animation) {                mCurrentAnimator = null;            }            @Override            public void onAnimationCancel(Animator animation) {                mCurrentAnimator = null;            }        });        set.start();        mCurrentAnimator = set;

5.Layout Changes

一行行许多view的添加和删除的动画效果

用到的是ViewGroup, 但确实没用动画效果

privateViewGroupmContainerView =(ViewGroup) findViewById(R.id.container);

这个R.id.container在布局文件中是一个LinearLayout

private void addItem() {        // Instantiate a new "row" view.        final ViewGroup newView = (ViewGroup) LayoutInflater.from(this).inflate(                R.layout.list_item_example, mContainerView, false);        // Set the text in the new row to a random country.        ((TextView) newView.findViewById(android.R.id.text1)).setText(                COUNTRIES[(int) (Math.random() * COUNTRIES.length)]);        // Set a click listener for the "X" button in the row that will remove the row.        newView.findViewById(R.id.delete_button).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                // Remove the row from its parent (the container view).                // Because mContainerView has android:animateLayoutChanges set to true,                // this removal is automatically animated.                mContainerView.removeView(newView);                // If there are no rows remaining, show the empty view.                if (mContainerView.getChildCount() == 0) {                    findViewById(android.R.id.empty).setVisibility(View.VISIBLE);                }            }        });        // Because mContainerView has android:animateLayoutChanges set to true,        // adding this view is automatically animated.        mContainerView.addView(newView, 0);    }

只是用ViewGroup的addView()和removeView(),是自带透明度动画效果,不算难。


二.ListViewAnimations 由三部分构成 Google cards example, Animation in adapter, Item manipulation

1.Google card example 这个效果真的很棒

point 1 LruCache

这里面不得不提的就是一个最核心的类是LruCache (此类在android-support-v4的包中提供)

import android.support.v4.util.LruCache;

首先要初始化:

privateLruCache<String,Bitmap>mMemoryCache;

 // 获取到可用内存的最大值,使用内存超出这个值会引起OutOfMemory异常。      // LruCache通过构造函数传入缓存值,以KB为单位。      int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);      // 使用最大可用内存值的1/8作为缓存的大小。      int cacheSize = maxMemory / 8;      mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {          @Override          protected int sizeOf(String key, Bitmap bitmap) {              // 重写此方法来衡量每张图片的大小,默认返回图片数量。              return bitmap.getByteCount() / 1024;          }      };  
还要写两个方法:
public void addBitmapToMemoryCache(String key, Bitmap bitmap) {      if (getBitmapFromMemCache(key) == null) {          mMemoryCache.put(key, bitmap);      }  }    public Bitmap getBitmapFromMemCache(String key) {      return mMemoryCache.get(key);  }  

当向 ImageView 中加载一张图片时,首先会在 LruCache 的缓存中进行检查。如果找到了相应的键值,则会立刻更新ImageView ,否则开启一个后台线程来加载这张图片。
public void loadBitmap(int resId, ImageView imageView) {      final String imageKey = String.valueOf(resId);      final Bitmap bitmap = getBitmapFromMemCache(imageKey);      if (bitmap != null) {          imageView.setImageBitmap(bitmap);      } else {          imageView.setImageResource(R.drawable.image_placeholder);          BitmapWorkerTask task = new BitmapWorkerTask(imageView);          task.execute(resId);      }  }  
BitmapWorkerTask 还要把新加载的图片的键值对放到缓存中。

class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {      // 在后台加载图片。      @Override      protected Bitmap doInBackground(Integer... params) {          final Bitmap bitmap = decodeSampledBitmapFromResource(                  getResources(), params[0], 100, 100);          addBitmapToMemoryCache(String.valueOf(params[0]), bitmap);          return bitmap;      }  }

好的,我们现在回到 Google card example

用到库里的很多东西 ,SwingBottomInAnimationAdapter从下方进入的效果,里面就是用到了使 Y 位移变化的动画

SwipeDismissAdapter 横滑消除的Adapter,其中含有 OnDissmissCallback 接口 ,还有 SwipeDismissListViewTouchListener

OnDismissCallback 是横滑删除的接口类 ; 在 GoogleCardAdapter中包含对LruCache的使用。

ListView listView = (ListView) findViewById(R.id.activity_googlecards_listview);mGoogleCardsAdapter = new GoogleCardsAdapter(this);SwingBottomInAnimationAdapter swingBottomInAnimationAdapter = new SwingBottomInAnimationAdapter(new SwipeDismissAdapter(mGoogleCardsAdapter, this));swingBottomInAnimationAdapter.setListView(listView);listView.setAdapter(swingBottomInAnimationAdapter);mGoogleCardsAdapter.addAll(getItems());



2.AnimationInExamples

是item view 出现的例子,有 SwingBottomIn,SwingRightIn,SwingLeftIn,SwingBottomRightIn,ScaleIn

SwingBottomIn 就是ListView+ Adapter, 只是这个Adapter被专门的效果Adapter所包裹。

BaseAdapter mAdapter = createListAdapter();SwingBottomInAnimationAdapter swingBottomInAnimationAdapter = new SwingBottomInAnimationAdapter(mAdapter);swingBottomInAnimationAdapter.setListView(getListView());getListView().setAdapter(swingBottomInAnimationAdapter);



三, ExpandingCell



附:ListView添加不同布局的item

http://www.eoeandroid.com/thread-72369-1-1.html

http://blog.csdn.net/lihonghao1017/article/details/10172493


很好的文章,记录开源项目的;

http://blog.tisa7.com/android_open_source_projects














更多相关文章

  1. Android(安卓)ScrollView嵌套Webview(实际使用CoordinatorLayout
  2. 填充Listview第一个Item的分隔线
  3. android 控件放大缩小效果实现
  4. Android(安卓)TabHost的使用(一)
  5. Android(安卓)对话框用法
  6. android > WebView > 获取表单数据
  7. 【Android】Android开源项目分类汇总
  8. Android——TextView指定字符串颜色高亮,实现类似微信、支付宝搜
  9. Android(安卓)仿58同城进度条加载内容动画效果的实现

随机推荐

  1. 【PostgreSQL技巧】PostgreSQL中的物化视
  2. 【PostgreSQL】PostgreSQL扩展:pg_stat_st
  3. 17 个 Ceph 日常运维常见难点和故障的解
  4. 「PostgreSQL」用MapReduce的方式思考,但
  5. 企业终端防御体系十大措施的设计部署与安
  6. 争议 | 基于存储网关 vs 基于存储引擎,两
  7. 【Postgres扩展】pg_auto_failover支持高
  8. 「PostgreSQL技巧」Citus实时执行程序如
  9. 「数据库架构」三分钟搞懂事务隔离级别和
  10. 「云转型」 可证实的企业云转型战略