Android Metro-style Launcher development series 3, androidmetro
Preface:
Dear friends, it's time to update the article every week. It was originally sent out on Sunday. Isn't it a catch-up with the Tomb Sweeping Day? The Queen spoke and played with her two or half days before the Tomb Sweeping Day, I will only write my blog on Monday afternoon. Where is the Queen? Where is it? There is oppression! Well, let's talk less about it. The previous blog (the second in the Android Metro-style Launcher development series) mentioned that the main framework of Launcher is implemented using ViewPager. this blog is about the specific implementation of each page.
PagerAdapter:
Launcher's main ViewPager implementation introduces PagerAdapter, Which is android. support. the class in the v4 package. Its sub-classes include FragmentPagerAdapter and FragmentStatePagerAdapter. These two adapters are both Fragment adapters. Here we will not talk about Fragment, so we will only talk about PagerAdapter. For the description of PageAapter, the original Google website is like this: Base class providing the adapter to populate pages inside of a ViewPager. you will most likely want to use a more specific implementation of this, such as FragmentPagerAdapter or FragmentStatePagerAdapter, that is, PagerAdapter is an adapter provided by ViewPager, so that we can control every View of ViewPager. My PagerAdapter is implemented as follows:
public class LauncherAdapter extends PagerAdapter { private ArrayList<PageViewItem> mViews; public LauncherAdapter(ArrayList<PageViewItem> views) { mViews = views; } @Override public void destroyItem(View arg0, int arg1, Object arg2) { ((ViewPager) arg0).removeView(mViews.get(arg1)); } @Override public void finishUpdate(View arg0) { } @Override public int getCount() { if (mViews != null) { return mViews.size(); } return 0; } public View getCurrentView(int currentID) { return mViews.get(currentID); } @Override public Object instantiateItem(View arg0, int arg1) { ((ViewPager) arg0).addView(mViews.get(arg1)); return mViews.get(arg1); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return (arg0 == arg1); } @Override public void restoreState(Parcelable arg0, ClassLoader arg1) { } @Override public Parcelable saveState() { return null; }}
PageViewItem:
Every view returned by the getCurrentView method of PagerAdapter is a custom View. Why? Because each icon will overlap with the icon next to it when the focus is enlarged, each page of ViewPager view is a FrameLayout, and the view is drawn in a certain order, after the focus view is enlarged, the display effect is partially compressed by the view next to it. This problem cannot be avoided if the view painting sequence is not changed.
As shown in, Figure 1 shows the effect of enlarging the focus view and changing the painting sequence. Changing the painting order is actually to override the getChildDrawingOrder (int childCount, int I) method of ViewGroup. During each painting, the index in the viewgroup where the focusview is located is returned.
CellView:
As shown in, each square view is called CellView here. It is also a custom view, which is mainly used for implementation:
1,Zoom out when the focus is obtained or when the focus is lost. Attribute animation is applied here. ViewPropertyAnimator can be obtained through the View's animate () method. The specific animation implementation is as follows:
mPropertyAnimator.scaleX((width + mScaleX) / width) .scaleY((height + mScaleY) / height).setDuration(duration) .setInterpolator(new DecelerateInterpolator()) .start();
2,You can flexibly configure some CellView attributes in the xml file, such as clicking the open application, the displayed ICON to obtain the address, and the focal point x and y to enlarge values. The attributes of CellView are defined as attrs. the xml file is as follows:
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="Launcher_ScaleView"> <attr name="parentID" format="integer" /> <attr name="resUrl" format="string" /> <attr name="resType" format="integer" /> <attr name="isRightEdge" format="boolean" /> <attr name="isLeftEdge" format="boolean" /> <attr name="isTopEdge" format="boolean" /> <attr name="isBottomEdge" format="boolean" /> <attr name="scaleX" format="integer" /> <attr name="scaleY" format="integer" /> <attr name="packageName" format="string" /> <attr name="activityName" format="string" /> <attr name="intentKey" format="string" /> <attr name="intentValue" format="string" /> <attr name="focusType" format="integer" /> </declare-styleable></resources>
3,The focus is not disordered when the remote control is used to move the focus. A major problem during the development of the remote control application is that the focus is disordered when the focus is shifted, basically, the app UI bug has at least half of the Focus bug. In this app, I defined the CellView boundary attribute to prevent focus disorder. In the above xml file, isXXEdge is, in this way, Page switching and other processing can be performed when the focus is moved to the boundary to prevent confusion when the focus enters every page.
The following describes the specific implementation results:
Conclusion: The above is the implementation of the Metro-style Launcher. I have used three blogs to explain this application. All effects are implemented by myself and there should be better implementation methods, you can share your opinions with me and pay attention to my account.Coder_onlineThank you!
Get a blog update reminder and share more technical information. Welcome to the personal public platform: programmer InterAction alliance.(Coder_online), Scan the QR code or search for the number belowCoder_onlineSo that we can communicate online.