Self-implementing sliding indicator Bar
First up 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 "android:layout_height=" 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
Give all the code first and then explain it step-by-step.
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);
}
}
}
From easy to difficult step by step.
1, Mypageradapter class
Generally our implementation of the adapter adapter is always new with a pageadapter instance. We made a little change here and set it up into a class with nothing changed, just one more constructor. So for the specific code of this class, I will no longer detail, if the function of the replication of which to write the students do not understand, please see "Viewpager detailed explanation (ii)---detailed four functions"
2. 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.
3, Mypagechangelistener ()---page change the 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.
This one is here, and the difficulty is not too much, it may not be too thin.
Source code, to everyone listed a tab interactive demo, the picture is as follows:
Using fragment to realize Viewpager sliding
using fragment to implement Viewpager sliding is an official recommendation of Android, so let's take a look at the 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
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), according to the parameters of the arg0, to return the current to display fragment, the following is the official explanation of GetItem, not very difficult, no longer detailed.
Public abstract Fragment GetItem (int position)
Return to the Fragment associated with a specified position.
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
Java code:
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;
}
Returns the view to display in Oncreateview (), which is a simple demonstration of how to manipulate the controls in the view, not much more difficult. 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>
Java code:
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.
4. Problems that may arise
Question: In mainactivity, when this sentence is written: Fragments.add (new Fragment1 ()); When you add an Fragement object instance to the fragment list, you are prompted "cannot convert Fragment1 () to Fragment"
Workaround: This is because the import package is inconsistent, and the general problem is that android.app.Fragment is imported into the Fragment1 and the class is imported here: Android.support.v4.app.Fragment, The package is different, of course, can not be converted, unified import as android.support.v4.app.Fragment after the normal