Items at the bottom of the ListView fly into the animation effect, listviewitem
Recently, a friend showed that the newly added item in the ListView Sliding Process has a sliding effect from the bottom. I think this effect is quite good, I thought about how to achieve this effect. After trying several solutions, I finally chose a simple way to use it.
Before sharing, let's take a look at what we need to do,
Well, have you seen any results? Take a closer look at the bottom of the sliding process. The newly added item will be added as an animation. Now, we will implement this effect!
Implementation Method Selection
When I first saw this effect, the first thing I thought of wasLayoutAnimation
But I was about to reject it soon. Why? The animation we can perform is only effective on the newly added item, but other items do not.LayoutAnimation
But how can we achieve this? The key point is when the animation is effective! We have said this many times,
The newly added item is added as an animation.
We only need to grasp this point and think about it soon.Adapter
OfgetView
When the new item is added, the getView of the Adapter must be executed. We will go down this way, and soon we will encounter problems,
How can we determine that it has slipped to the bottom?
Many people will answer this question without thinking about it. This is easy! This is not the same as the pagination of ListView! Of course not. The bottom of the ListView page is the last item of the dataset to be judged. It is not suitable for us here. We have not found a proper method for using the ListView methods, we can only judge it by ourselves. How can we judge it? Still listeningOnScrollListener
In this case, determine whether it is sliding down. As to whether it is at the bottom, submit it to getView! Therefore, we also need to know the existence of the ListView In the Adapter and set a sliding listener for it.
Assume that we can now determine to slide to the bottom. We use a state variable.isScrollDown
So that we cangetView
PassedisScrollDown
To determine whether to giveconvertView
What about an animation?
The basic implementation ideas have been elaborated. Next we will use code to implement our ideas. We need to solve the following problems,
For the first problem, we use the following methods in most cases:
Customize an abstract Adapter, implement the getView method in BaseAdapter, and define a buildView
To replace the getView function.
The advantage of doing so is that we can do what we want to do in getView without worrying about how convertView is formed. This is also very suitable for our needs, so the code can be written like this,
public abstract class BaseFlyAdapter extends BaseAdapter { public View getView(int position, View convertView, ViewGroup parent) { View view = buildView(position, convertView, parent); return view; } public abstract View buildView(int position, View convertView, ViewGroup parent);}
As mentioned above, we need to monitor the slide of the ListView. Here we can also handle it in BaseFlyAdapter! Then we need a ListView for BaseFlyAdapter and set it for him.OnScrollListener
,
public abstract class BaseFlyAdapter extends BaseAdapter { private ListView mListView; public void bindView(ListView listView) { mListView = listView; mListView.setOnScrollListener(mScrollListener); } private OnScrollListener mScrollListener = new OnScrollListener() { public void onScrollStateChanged(AbsListView view, int scrollState) { } public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { } }; ...}
If you have prepared these items, we will implement them.If you determine to slide down
For this requirement, first go to the code,
Public abstract class BaseFlyAdapter extends BaseAdapter {private ListView mListView; private boolean isScrollDown; // whether to slide down private int mFirstPosition; // The Position of the first visible item private int mFirstTop; // The first item can have the top value public void bindView (ListView listView) {mListView = listView; mListView. setOnScrollListener (mScrollListener);} private OnScrollListener mScrollListener = new OnScrollListener () {public void onScrollStateChanged (AbsListView view, int scrollState) {if (scrollState = OnScrollListener. SCROLL_STATE_IDLE) isScrollDown = false;} public void onScroll (AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {View firstChild = view. getChildAt (0); if (firstChild = null) return; int top = firstChild. getTop (); isScrollDown = firstVisibleItem> mFirstPosition | mFirstTop> top; mFirstTop = top; mFirstPosition = firstVisibleItem ;}};}
The specific code ismScrollListener
First, let's take a lookonScrollStateChanged
The code here is very simple, that is, it is restored when the sliding stops.isScrollDown
Variable. The most important code isonScroll
. Let's take a look at the implementation here.
First, we get the first view of ListView --firstChild
If you do not understand what is going on here, you can go to the ListView reuse mechanism and then we can getfirstChild
The top value of, these are all for the following to determine whether it is prepared to slide down, then how to determine?
isScrollDown = firstVisibleItem > mFirstPosition || mFirstTop > top;
OneOrHere, we need to consider two situations,
The first case is a conventional case. We can determine the first visible item directly.First visible itemIt refers to the firstVisibleItem in our dataset and determines whether it is greater than the previously saved firstVisibleItem. You can check the final code and save the top values of firstVisibleItem and the first View. In the second case, we only need to determine whether the top value of the View is greater than the value we saved last time.
Okay. So far, we can see if the ListView slides down. Next, we will add an animation to the newly added item. To make the animation more flexible, we needBaseFlyAdapter
One way to set an animation,
public abstract class BaseFlyAdapter extends BaseAdapter { private AnimationSet mAnimationSet; ... public void setAnimation(AnimationSet set) { mAnimationSet = set; } ...}
After the animation is set, let's see how to do it in getView. As mentioned above, the animation is executed in getView,
public abstract class BaseFlyAdapter extends BaseAdapter { ... public View getView(int position, View convertView, ViewGroup parent) { View view = buildView(position, convertView, parent); if(isScrollDown && mAnimationSet != null) { cancelAnimation(); view.startAnimation(mAnimationSet); } return view; } private void cancelAnimation() { int count = mListView.getChildCount(); for(int i=0;i<count;i++) { mListView.getChildAt(i).clearAnimation(); } }}
First, call buildView. The code we previously wrote in getView needs to be put in buildView now. Then, we can determine whether the current code is sliding down. If it is sliding down, first, cancel removes the animation of all items. The purpose is to prevent multiple items from executing the animation at a certain moment, and then directly call convertView. startAnimation to start the animation. But do you still remember the above sentence?
If it is at the bottom, submit it to getView!
We can see that there is no code in the getView code to solve this problem! Yes, there is no error. If getView is executed, the new item must have been added, and we have made a judgment on whether to slide down in getView, so this problem is solved naturally!
OK, OK, everything is ready. Let's start using it,
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ListView listView = (ListView) findViewById(R.id.list); MyAdapter adapter = new MyAdapter(); adapter.bindView(listView); adapter.setAnimation((AnimationSet) AnimationUtils.loadAnimation(this, R.anim.anim)); listView.setAdapter(adapter); }}
Ignore the code of MyAdapter first. It must have inherited the BaseFlyAdapter we defined. We set an animation through setAnimation. Let's take a look at how this animation is written,
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="500" android:fromYDelta="50%" android:toYDelta="0" /></set>
Not to mention, a simple translate animation.
Finally, let's take a look at MyAdapter. In fact, it is the same as inheriting BaseAdapter, but we don't need to write the getView code, but put it in buildView,
class MyAdapter extends BaseFlyAdapter { public int getCount() { return 100; } public Object getItem(int position) { return "hello"; } public long getItemId(int position) { return position; } @Override public View buildView(int position, View convertView, ViewGroup parent) { if(convertView == null) { convertView = View.inflate(parent.getContext(), R.layout.item, null); } return convertView; }}
Now you can take a look at the effect. Of course, we have extracted the animation definition here. The advantage of doing so is that you can switch the animation at will. Now we can change the animation to an alpha animation,
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" > <alpha android:duration="500" android:fillAfter="true" android:fromAlpha="0.0" android:toAlpha="1.0"/></set>
Our code does not need to be changed. Let's take a look at the effect,
It's easy, and the alpha effect is complete. That's it.
Click here to download the code.
Copyright Disclaimer: This article is from the Loader's Blog and cannot be reproduced without the permission of the blogger.