android 动态效果学习之旅

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

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

1.Simple Crossfade

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

 

  1. privatevoid showContentOrLoadingIndicator(boolean contentLoaded) {
  2. // Decide which view to hide and which to show.
  3. final View showView = contentLoaded ? mContentView : mLoadingView;
  4. final View hideView = contentLoaded ? mLoadingView : mContentView;
  5. // Set the "show" view to 0% opacity but visible, so that it is visible
  6. // (but fully transparent) during the animation.
  7. showView.setAlpha(0f);
  8. showView.setVisibility(View.VISIBLE);
  9. // Animate the "show" view to 100% opacity, and clear any animation listener set on
  10. // the view. Remember that listeners are not limited to the specific animation
  11. // describes in the chained method calls. Listeners are set on the
  12. // ViewPropertyAnimator object for the view, which persists across several
  13. // animations.
  14. showView.animate()
  15. .alpha(1f)
  16. .setDuration(mShortAnimationDuration)
  17. .setListener(null);
  18. // Animate the "hide" view to 0% opacity. After the animation ends, set its visibility
  19. // to GONE as an optimization step (it won't participate in layout passes, etc.)
  20. hideView.animate()
  21. .alpha(0f)
  22. .setDuration(mShortAnimationDuration)
  23. .setListener(new AnimatorListenerAdapter() {
  24. @Override
  25. publicvoid onAnimationEnd(Animator animation) {
  26. hideView.setVisibility(View.GONE);
  27. }
  28. });
  29. }
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 abstract FragmentTransaction setCustomAnimations(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. The popEnter and popExit animations will be played for enter/exit operations specifically when popping the back stack.

这是一个卡片翻转正背面切换的效果,做的其实一般。

  1. if (savedInstanceState == null) {
  2. // If there is no saved instance state, add a fragment representing the
  3. // front of the card to this activity. If there is saved instance state,
  4. // this fragment will have already been added to the activity.
  5. getFragmentManager()
  6. .beginTransaction()
  7. .add(R.id.container, new CardFrontFragment())
  8. .commit();
  9. } else {
  10. mShowingBack = (getFragmentManager().getBackStackEntryCount() > 0);
  11. }
  12. // Monitor back stack changes to ensure the action bar shows the appropriate
  13. // button (either "photo" or "info").
  14. getFragmentManager().addOnBackStackChangedListener(this);
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()配合,这一点值得学习。

  1. privatevoid flipCard() {
  2. if (mShowingBack) {
  3. getFragmentManager().popBackStack();
  4. return;
  5. }
  6. // Flip to the back.
  7. mShowingBack = true;
  8. // Create and commit a new fragment transaction that adds the fragment for the back of
  9. // the card, uses custom animations, and is part of the fragment manager's back stack.
  10. getFragmentManager()
  11. .beginTransaction()
  12. .setCustomAnimations(
  13. R.animator.card_flip_right_in, R.animator.card_flip_right_out,
  14. R.animator.card_flip_left_in, R.animator.card_flip_left_out)
  15. // Replace any fragments currently in the container view with a fragment
  16. .replace(R.id.container, new CardBackFragment())
  17. // Add this transaction to the back stack, allowing users to press Back
  18. // to get to the front of the card.
  19. .addToBackStack(null)
  20. // Commit the transaction.
  21. .commit();
  22. // Defer an invalidation of the options menu (on modern devices, the action bar). This
  23. // can't be done immediately because the transaction may not yet be committed. Commits
  24. // are asynchronous in that they are posted to the main thread's message loop.
  25. mHandler.post(new Runnable() {
  26. @Override
  27. publicvoid run() {
  28. invalidateOptionsMenu();
  29. }
  30. });
  31. }
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();
            }
        });
    }

 

 

 

  1. @Override
  2. publicvoid onBackStackChanged() {
  3. mShowingBack = (getFragmentManager().getBackStackEntryCount() > 0);
  4. // When the back stack changes, invalidate the options menu (action bar).
  5. invalidateOptionsMenu();
  6. }
@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;

 

 

  1. // Instantiate a ViewPager and a PagerAdapter.
  2. mPager = (ViewPager) findViewById(R.id.pager);
  3. mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager());
  4. mPager.setAdapter(mPagerAdapter);
  5. mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
  6. @Override
  7. publicvoid onPageSelected(int position) {
  8. // 更新actionbar的menu,可以借鉴
  9. invalidateOptionsMenu();
  10. }
  11. });
// 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();
            }
        });

 

  1. @Override
  2. publicboolean onCreateOptionsMenu(Menu menu) {
  3. super.onCreateOptionsMenu(menu);
  4. getMenuInflater().inflate(R.menu.activity_screen_slide, menu);
  5. menu.findItem(R.id.action_previous).setEnabled(mPager.getCurrentItem() > 0);
  6. // 这个很好,我一般就只用上面的,没想到这里还可以这样写
  7. MenuItem item = menu.add(Menu.NONE, R.id.action_next, Menu.NONE,
  8. (mPager.getCurrentItem() == mPagerAdapter.getCount() - 1)
  9. ? R.string.action_finish
  10. : R.string.action_next);
  11. item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
  12. returntrue;
  13. }
@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;
    }

顺便把这个也贴上吧,要不感觉不完整

 

 

  1. @Override
  2. publicboolean onOptionsItemSelected(MenuItem item) {
  3. switch (item.getItemId()) {
  4. case android.R.id.home:
  5. // Navigate "up" the demo structure to the launchpad activity.
  6. // See http://developer.android.com/design/patterns/navigation.html for more.
  7. NavUtils.navigateUpTo(this, new Intent(this, MainActivity.class));
  8. returntrue;
  9. case R.id.action_previous:
  10. // Go to the previous step in the wizard. If there is no previous step,
  11. // setCurrentItem will do nothing.
  12. mPager.setCurrentItem(mPager.getCurrentItem() - 1);
  13. returntrue;
  14. case R.id.action_next:
  15. // Advance to the next step in the wizard. If there is no next step, setCurrentItem
  16. // will do nothing.
  17. mPager.setCurrentItem(mPager.getCurrentItem() + 1);
  18. returntrue;
  19. }
  20. returnsuper.onOptionsItemSelected(item);
  21. }
@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();

 

  1. publicstatic ScreenSlidePageFragment create(int pageNumber) {
  2. ScreenSlidePageFragment fragment = new ScreenSlidePageFragment();
  3. Bundle args = new Bundle();
  4. args.putInt(ARG_PAGE, pageNumber);
  5. fragment.setArguments(args);
  6. return fragment;
  7. }
  8. @Override
  9. publicvoid onCreate(Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. mPageNumber = getArguments().getInt(ARG_PAGE);
  12. }
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中,

  1. <resourcesxmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
  2. <stringname="title_template_step">Step <xliff:gid="step_number">%1$d</xliff:g>: Lorem Ipsum</string>
<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>

 

  1. // Set the title view to show the page number.
  2. ((TextView) rootView.findViewById(android.R.id.text1)).setText(
  3. getString(R.string.title_template_step, mPageNumber + 1))
 // 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

再举个例子:
  1. <stringname="time">当前时间:<xliff:gid="prefix">%1$s</xliff:g><xliff:gid="time">%2$s</xliff:g></string>
  2. //然后通过程序,context.getString(R.string.time,"10","05");
<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的比例,距离计算,和动画的设计。

 

  1. AnimatorSet set = new AnimatorSet();
  2. set
  3. .play(ObjectAnimator.ofFloat(expandedImageView, View.X, startBounds.left,
  4. finalBounds.left))
  5. .with(ObjectAnimator.ofFloat(expandedImageView, View.Y, startBounds.top,
  6. finalBounds.top))
  7. .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X, startScale, 1f))
  8. .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y, startScale, 1f));
  9. set.setDuration(mShortAnimationDuration);
  10. set.setInterpolator(new DecelerateInterpolator());
  11. set.addListener(new AnimatorListenerAdapter() {
  12. @Override
  13. publicvoid onAnimationEnd(Animator animation) {
  14. mCurrentAnimator = null;
  15. }
  16. @Override
  17. publicvoid onAnimationCancel(Animator animation) {
  18. mCurrentAnimator = null;
  19. }
  20. });
  21. set.start();
  22. mCurrentAnimator = set;
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, 但确实没用动画效果

private ViewGroup mContainerView =(ViewGroup) findViewById(R.id.container);

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

  1. privatevoid addItem() {
  2. // Instantiate a new "row" view.
  3. final ViewGroup newView = (ViewGroup) LayoutInflater.from(this).inflate(
  4. R.layout.list_item_example, mContainerView, false);
  5. // Set the text in the new row to a random country.
  6. ((TextView) newView.findViewById(android.R.id.text1)).setText(
  7. COUNTRIES[(int) (Math.random() * COUNTRIES.length)]);
  8. // Set a click listener for the "X" button in the row that will remove the row.
  9. newView.findViewById(R.id.delete_button).setOnClickListener(new View.OnClickListener() {
  10. @Override
  11. publicvoid onClick(View view) {
  12. // Remove the row from its parent (the container view).
  13. // Because mContainerView has android:animateLayoutChanges set to true,
  14. // this removal is automatically animated.
  15. mContainerView.removeView(newView);
  16. // If there are no rows remaining, show the empty view.
  17. if (mContainerView.getChildCount() == 0) {
  18. findViewById(android.R.id.empty).setVisibility(View.VISIBLE);
  19. }
  20. }
  21. });
  22. // Because mContainerView has android:animateLayoutChanges set to true,
  23. // adding this view is automatically animated.
  24. mContainerView.addView(newView, 0);
  25. }
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;

首先要初始化:

private LruCache<String, Bitmap> mMemoryCache;

  1. // 获取到可用内存的最大值,使用内存超出这个值会引起OutOfMemory异常。
  2. // LruCache通过构造函数传入缓存值,以KB为单位。
  3. int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
  4. // 使用最大可用内存值的1/8作为缓存的大小。
  5. int cacheSize = maxMemory / 8;
  6. mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
  7. @Override
  8. protectedint sizeOf(String key, Bitmap bitmap) {
  9. // 重写此方法来衡量每张图片的大小,默认返回图片数量。
  10. return bitmap.getByteCount() / 1024;
  11. }
  12. };
 // 获取到可用内存的最大值,使用内存超出这个值会引起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;  
        }  
    };  

还要写两个方法:

  1. publicvoid addBitmapToMemoryCache(String key, Bitmap bitmap) {
  2. if (getBitmapFromMemCache(key) == null) {
  3. mMemoryCache.put(key, bitmap);
  4. }
  5. }
  6. public Bitmap getBitmapFromMemCache(String key) {
  7. return mMemoryCache.get(key);
  8. }
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 ,否则开启一个后台线程来加载这张图片。

  1. <span style="font-size: 14px;">publicvoid loadBitmap(int resId, ImageView imageView) {
  2. final String imageKey = String.valueOf(resId);
  3. final Bitmap bitmap = getBitmapFromMemCache(imageKey);
  4. if (bitmap != null) {
  5. imageView.setImageBitmap(bitmap);
  6. } else {
  7. imageView.setImageResource(R.drawable.image_placeholder);
  8. BitmapWorkerTask task = new BitmapWorkerTask(imageView);
  9. task.execute(resId);
  10. }
  11. } </span>
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 还要把新加载的图片的键值对放到缓存中。

 

  1. <span style="font-size: 14px;">class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
  2. // 在后台加载图片。
  3. @Override
  4. protected Bitmap doInBackground(Integer... params) {
  5. final Bitmap bitmap = decodeSampledBitmapFromResource(
  6. getResources(), params[0], 100, 100);
  7. addBitmapToMemoryCache(String.valueOf(params[0]), bitmap);
  8. return bitmap;
  9. }
  10. }</span>
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的使用。

  1. ListView listView = (ListView) findViewById(R.id.activity_googlecards_listview);
  2. mGoogleCardsAdapter = new GoogleCardsAdapter(this);
  3. SwingBottomInAnimationAdapter swingBottomInAnimationAdapter = new SwingBottomInAnimationAdapter(
  4. new SwipeDismissAdapter(mGoogleCardsAdapter, this));
  5. swingBottomInAnimationAdapter.setListView(listView);
  6. listView.setAdapter(swingBottomInAnimationAdapter);
  7. mGoogleCardsAdapter.addAll(getItems());
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所包裹。

  1. BaseAdapter mAdapter = createListAdapter();
  2. SwingBottomInAnimationAdapter swingBottomInAnimationAdapter = new SwingBottomInAnimationAdapter(
  3. mAdapter);
  4. swingBottomInAnimationAdapter.setListView(getListView());
  5. getListView().setAdapter(swingBottomInAnimationAdapter);
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


原文:http://blog.csdn.net/mennoa/article/details/18708209

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值