Self-implementing sliding indicator Bar
First, a basic effect chart:
1.XML layout
The layout code is as follows:
<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:tools= "http:// Schemas.android.com/tools "
android:layout_width=" match_parent "
android:layout_height=" Match_parent "
android:orientation= "vertical"
tools:context= "com.example.testviewpage_2.MainActivity" >
< ImageView
android:id= "@+id/cursor"
android:layout_width= "Fill_parent"
Wrap_content "
android:scaletype=" Matrix "
android:src=" @drawable/a "/>
< Android.support.v4.view.ViewPager
android:id= "@+id/viewpager"
android:layout_width= "Wrap_content"
android:layout_height= "wrap_content"
android:layout_gravity= "center"/>
</linearlayout >
With a linear vertical layout, add a small horizontal bar above the sliding page.
2.JAVA Code
public class Mainactivity extends activity {private View view1, View2, VIEW3; Private list<view> viewlist;//View array private Viewpager Viewpager;
The corresponding Viewpager private imageview cursor; private int BMPW = 0; Cursor width private int offset = 0;////animation picture offset private int currindex = 0;//Current page card number @Override protected void Oncrea
Te (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Viewpager = (Viewpager) Findviewbyid (R.id.viewpager);
Layoutinflater inflater = Getlayoutinflater ();
View1 = inflater.inflate (R.LAYOUT.LAYOUT1, NULL);
View2 = inflater.inflate (r.layout.layout2, NULL);
VIEW3 = inflater.inflate (R.LAYOUT.LAYOUT3, NULL);
Viewlist = new arraylist<view> ()//The View to be displayed is loaded into the array viewlist.add (VIEW1);
Viewlist.add (VIEW2);
Viewlist.add (VIEW3);
Initialize indicator position initcursorpos ();
Viewpager.setadapter (New Mypageradapter (viewlist)); Viewpager.setonpagechangelistenER (new Mypagechangelistener ());
}//Initialize indicator position public void Initcursorpos () {//Initialize animation cursor = (ImageView) Findviewbyid (r.id.cursor); BMPW = Bitmapfactory.decoderesource (Getresources (), R.drawable.a). GetWidth ()//Get picture width displaymetrics dm = new
Displaymetrics ();
Getwindowmanager (). Getdefaultdisplay (). Getmetrics (DM); int screenw = dm.widthpixels;//Get resolution width offset = (screenw/viewlist.size ()-BMPW)/2;//compute offset Matrix matrix = n
EW Matrix ();
Matrix.posttranslate (offset, 0); Cursor.setimagematrix (matrix),//Set animation initial position}//page change Listener public class Mypagechangelistener implements Onpagechange
Listener {int one = offset * 2 + bmpw;//page card 1-> page Card 2 offset int two = one * 2;//page Card 1-> page Card 3 offset @Override
public void onpageselected (int arg0) {Animation Animation = null;
Switch (arg0) {case 0:if (currindex = = 1) {animation = new Translateanimation (one, 0, 0, 0);
else if (Currindex = 2) {Animation = new Translateanimation (two, 0, 0, 0);
} break;
Case 1:if (Currindex = = 0) {animation = new Translateanimation (offset, one, 0, 0);
else if (Currindex = 2) {animation = new Translateanimation (two, one, 0, 0);
} break;
Case 2:if (Currindex = = 0) {animation = new Translateanimation (offset, two, 0, 0);
else if (Currindex = 1) {animation = new Translateanimation (one, two, 0, 0);
} break;
} currindex = arg0;
Animation.setfillafter (TRUE);/true: The picture stops at the animation end position Animation.setduration (300);
Cursor.startanimation (animation); @Override public void onpagescrolled (int arg0, float arg1, int arg2) {} @Override public void OnPage scrollstatechanged (int arg0) {}}/** * Viewpager adapter/public class Mypageradapter extends
{public list<view> mlistviews; Public Mypageradapter (list<view> mlistviews) {This.mlisTviews = Mlistviews; @Override public boolean isviewfromobject (View arg0, Object arg1) {//TODO auto-generated method stub R
Eturn arg0 = = arg1;
@Override public int GetCount () {//TODO auto-generated a stub return mlistviews.size (); @Override public void Destroyitem (ViewGroup container, int position, object) {//TODO auto-generated
Method Stub Container.removeview (Mlistviews.get (position)); @Override public Object Instantiateitem (viewgroup container, int position) {//TODO auto-generated method s
Tub Container.addview (mlistviews.get (position));
return Mlistviews.get (position);
}
}
}
3. Focus Analysis
from easy to difficult step by step.
(1) initcursorpos ()---initialization indicator position
when the cursor is initialized, we want to display the cursor position based on the screen width. Let's take a look at this part of the code:
Initialize indicator position public
void Initcursorpos () {
//Initialize animation
cursor = (imageview) Findviewbyid (r.id.cursor);
BMPW = Bitmapfactory.decoderesource (Getresources (), R.drawable.a)
. GetWidth ()//Get picture width
displaymetrics dm = New Displaymetrics ();
Getwindowmanager (). Getdefaultdisplay (). Getmetrics (DM);
int screenw = dm.widthpixels;//Get resolution width
offset = (screenw/viewlist.size ()-BMPW)/2;//compute offset
Matrix matrix = New Matrix ();
Matrix.posttranslate (offset, 0);
Cursor.setimagematrix (matrix);//Set animation initial position
}
Some students may not understand the position is that the initialization of the location of the offset why so counted, the following, I drew a picture, look at the next should understand.
Finally for the offset method, a lot of available, here The imitation of the Internet code with the matrix, of course, you can use the other offset method, the same.
(2) Mypagechangelistener ()---page change listener
the code is as follows:
public class Mypagechangelistener implements Onpagechangelistener {int one = offset * 2 + bmpw;//page card 1-> page Card 2 offset int two = one * 2;//page Card 1-> page Card 3 offset @Override public void onpageselected (int arg0) {Animation Animation = n
ull;
Switch (arg0) {case 0:if (currindex = = 1) {animation = new Translateanimation (one, 0, 0, 0);
else if (Currindex = = 2) {animation = new Translateanimation (two, 0, 0, 0);
} break;
Case 1:if (Currindex = = 0) {animation = new Translateanimation (offset, one, 0, 0);
else if (Currindex = 2) {animation = new Translateanimation (two, one, 0, 0);
} break;
Case 2:if (Currindex = = 0) {animation = new Translateanimation (offset, two, 0, 0);
else if (Currindex = 1) {animation = new Translateanimation (one, two, 0, 0);
} break;
} currindex = arg0;
Animation.setfillafter (TRUE);/true: The picture stops at the animation end position Animation.setduration (300); Cursor.startanimation (animation);
}
The principle is that, depending on the slide to the page, slide the cursor to the specified position.
There may be difficulty in this place, in mathematics ...
I drew a picture of why the distance from the first page to the second page was "cursor width +offset*2," and other distances were similar.
Using fragment to realize Viewpager sliding
Effect Chart:
Add a btn to the first page
The first page slides toward the second page
The second page slides towards the third page
Some notes:
Fragmentpageradapter is derived from Pageradapter, which is used to render fragment pages, which are kept in Fragment manager so that users can access them at any time.
This adapter is best used for limited static fragment page management. Although views that are not visible are sometimes destroyed, all fragment accessed by the user are saved in memory. So the fragment instance saves a large number of States, which creates a lot of memory overhead. So if you want to handle a lot of page transitions, it's recommended to use Fragmentstatepageradapter.
Every viewpager that uses fragmentpageradapter must have a valid set of IDs, and a collection of valid IDs is a collection of fragment (thanks to the prompts of the students)
For Fragmentpageradapter derived classes, it is only necessary to override the GetItem (int) and GetCount ().
Specific implementation:
1, adapter implementation--fragmentpageradapter
First look at the complete code, and then detail:
public class Fragadapter extends Fragmentpageradapter {
private list<fragment> mfragments;
Public Fragadapter (Fragmentmanager fm,list<fragment> fragments) {
super (FM);
TODO auto-generated constructor stub
mfragments=fragments;
}
@Override public
Fragment getitem (int arg0) {
//TODO auto-generated a stub return
mfragments.get ( arg0);
}
@Override public
int GetCount () {
//TODO auto-generated a stub return
mfragments.size ();
}
}
Here are three functions, according to the official document of the first part, that for fragmentpageradapter derived classes, only the getitem (int) and GetCount () can be overridden.
For constructors, a fragment list object is applied here to hold the fragment object for sliding and initialize it in the creation function:
Public Fragadapter (Fragmentmanager fm,list<fragment> fragments) {
super (FM);
TODO auto-generated constructor stub
mfragments=fragments;
}
Then, in GetItem (int arg0), the fragment that is currently being displayed is returned based on the arguments that came arg0.
Finally, GetCount () returns the total number of fragment used for sliding;
From the constructor, we can see that we are going to construct a set of fragment, so we first produce the fragment class we need;
2, three fragment class
First Fragment class:
XML: (Layout1.xml)
<?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: Background= "#ffffff"
android:orientation= "vertical" >
<button android:id= "@+id/fragment1_btn"
Android:layout_width= "Wrap_content"
android:layout_height= "wrap_content"
android:text= "show Toast"
/>
</LinearLayout>
In which a BTN was added
public class Fragment1 extends Fragment {
@Override public
View Oncreateview (layoutinflater inflater, ViewGroup Container,
Bundle savedinstancestate) {
//TODO auto-generated method stub
View view= Inflater.inflate ( R.LAYOUT.LAYOUT1, container, false);
Action method
Button btn = (button) View.findviewbyid for controls in view (R.ID.FRAGMENT1_BTN);
Btn.setonclicklistener (New View.onclicklistener () {
@Override public
void OnClick (View v) {
//TODO auto-generated method Stub
Toast.maketext (Getactivity (), "clicked the btn of the first fragment", Toast.length_short). Show ();
});
return view;
}
In Oncreateview () to return to display view, the above code simply demonstrates how to manipulate the control in the view, not difficult, no longer detailed, if the fragment not too familiar with the classmate, first look at this article: "Android fragment fully resolved, Everything you need to know about the pieces
Second Fragment class:
XML code: (layout2.xml) native code, without making any changes
<?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: Background= "#ffff00"
android:orientation= "vertical" >
</LinearLayout>
public class Fragment2 extends Fragment {
@Override public
View Oncreateview (Layoutinflater inflater, ViewGroup container,
Bundle savedinstancestate) {
//TODO auto-generated method stub
View view= Inflater.inflate (R.layout.layout2, container, false);
return view;
}
A third fragment class:
XML code: (Layout3.xml) Same, native code, no changes made
<?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: Background= "#ff00ff"
android:orientation= "vertical" >
</LinearLayout>
Java code:
public class Fragment3 extends Fragment {
@Override public
View Oncreateview (Layoutinflater inflater, ViewGroup container,
Bundle savedinstancestate) {
//TODO auto-generated method stub
View view= Inflater.inflate (R.LAYOUT.LAYOUT3, container, false);
return view;
}
3, the main activity to achieve
Core Code:
public class Mainactivity extends Fragmentactivity {
@Override
protected void OnCreate (Bundle Savedinstancestate) {
super.oncreate (savedinstancestate);
Setcontentview (r.layout.activity_main);
Construct Adapter
list<fragment> fragments=new arraylist<fragment> ();
Fragments.add (New Fragment1 ());
Fragments.add (New Fragment2 ());
Fragments.add (New Fragment3 ());
Fragadapter adapter = new Fragadapter (Getsupportfragmentmanager (), fragments);
Set adapter
Viewpager VP = (viewpager) Findviewbyid (R.id.viewpager);
Vp.setadapter (adapter);
}
First of all, there is a most noteworthy place: activity derived from fragmentactivity, in fact, this is the basic knowledge of fragment, only fragmentactivity can be embedded fragment page, ordinary activity is not.
This code is mainly divided into two steps, the first step: the construction of the adapter, the second step: set the adapter.
First look at the process of constructing the adapter:
Construct Adapter
list<fragment> fragments=new arraylist<fragment> ();
Fragments.add (New Fragment1 ());
Fragments.add (New Fragment2 ());
Fragments.add (New Fragment3 ());
Fragadapter adapter = new Fragadapter (Getsupportfragmentmanager (), fragments);
Constructs a fragment list and then adds the corresponding instances of the three fragment classes above, and finally generates fragadapter instances.
As for the second step, set the adapter, there is nothing to talk about.