Preface:
about using Viewpageindicator and Viewpager to implement tab navigation, there are already a bunch of blogs about it in the development community, assuming I'm still writing about how to do it here. It's a cliché, no novelty, and. I do not feel that my understanding of viewpageindicator will be better than others, after all, I also look at the post of the great God. In the learning practice.
So what's the point of writing this? In fact, I just want to write it down here. When you use Viewpageindicator and Viewpager to implement tab navigation, you are likely to encounter pits. This pit. It needs to be avoided as much as we develop.
What? You asked me why I knew about these pits?
As I have just met, just conquered. So come and share the experience!
First, recommended blog
Before you introduce the specific implementation code. I first introduced two blog Bai, after all, I am based on what they write to learn. The first "Android Open source framework viewpageindicator and Viewpager Imitation NetEase news clienttab label" This blog on how to Implement tab has been introduced very specific, including how to define the tab style, please learn to worship it ... Let's say you have a poor learning ability, well, there is a teaching video in Mu-class online. This but Hung Xiang great God recorded Oh, 4-1 viewpagerindicator and viewpager realize tab, assuming you see the video will not, that I, hehe ...
second, how to import Viewpageindicator in Android studio
People who have read my blog and video before will ask, in Eclipse, we directly introduce the Viewpageindicator project. I'll just do it again. Android-support-v4.jar package for the next treatment. So, how do I import the Viewpageindicator project in Android Studio ?
Well, let me tell you. Please see:
See, we only need to search for com.inkapplications.viewpageindicator here, select. Click OK. Gradle will take the initiative to help me change project into the.
Let's see after the import. Where is the source code?:
When you need to change the resource file. Can be directly in the Res folder under the resource file to make changes, is not very convenient!!
!
Now one thing to remember. Since you changed the project has introduced android-support-v4, so you do not need to introduce other V4 package, remember!!!
third, the Realization of tab navigation3.1 Main Page layout
<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width= "Fill_ Parent " android:layout_height=" fill_parent " android:orientation=" vertical "> < Com.viewpagerindicator.TabPageIndicator android:id= "@+id/tab_page_indicator" android:layout_width= " Fill_parent " android:layout_height=" 60DP "/> <android.support.v4.view.viewpager android:id=" @+id/study_viewpager " android:layout_width=" fill_parent " android:layout_height=" Fill_parent "/> </LinearLayout>
3.2 Defining the Viewpager to display fragment
Import Android.os.bundle;import Android.support.v4.app.fragment;import Android.view.layoutinflater;import Android.view.view;import Android.view.viewgroup;import Com.lidroid.xutils.viewutils;public class FragmentStudy Extends Fragment { private view view = null; @Override public View Oncreateview (layoutinflater inflater, ViewGroup container, Bundle savedinstancestate) { if (view==null) { view = inflater.inflate (R.layout.fragment_study, container, false); } Viewutils.inject (this, view); return view;} }
Fragment_study.xml file:
<?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:orientation=" Vertical "> <textview android:id=" @+id/text_name " android:layout_width=" Fill_parent " android:layout_height= "Fill_parent" android:gravity= "center" android:text= "missed" android:textsize= " 25SP "/></linearlayout>
3.3 Defining the adapter of Viewpager
public class Projectpageradapter extends Fragmentpageradapter {private static string[] titles = {"All", "planned", "in Progress", " Completed "}; Public Projectpageradapter (fragmentmanager FM) {super (FM); } @Override public Fragment getItem (int position) {Fragment Fragment = null; Bundle bundle = NULL; Switch (position) {Case 0:fragment = new Fragmentstudy (); bundle = new Bundle (); Bundle.putint ("Pos", 0); Fragment.setarguments (bundle); Break Case 1:fragment = new Fragmentstudy (); bundle = new Bundle (); Bundle.putint ("pos", 1); Fragment.setarguments (bundle); Break Case 2:fragment = new Fragmentstudy (); bundle = new Bundle (); Bundle.putint ("Pos", 2); Fragment.setarguments (bundle); Break Case 3:fragment = new Fragmentstudy (); bundle = new Bundle (); Bundle.putint ("POS", 3); Fragment.setarguments (bundle); Break } return fragment; } @Override public int getcount () {return titles.length; } @Override public charsequence getpagetitle (int position) {return titles[position]; }}
3.4 Setting Viewpageindicator and Viewpager
import android.os.bundle;import Android.support.v4.app.fragmentactivity;import Android.support.v4.view.viewpager;import Com.lidroid.xutils.viewutils;import Com.lidroid.xutils.view.annotation.viewinject;import Com.viewpagerindicator.tabpageindicator;public Class Mainactivity extends Fragmentactivity {@ViewInject (r.id.tab_page_indicator) Private Tabpageindicator Tabpageindicat Or @ViewInject (R.id.study_viewpager) private Viewpager Studyviewpager; Private Projectpageradapter Madatpter; @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); Viewutils.inject (this); Madatpter = new Projectpageradapter (Getsupportfragmentmanager ());//Here, suppose not the inherited fragmentactivity, but the inherited fragment, Then the parameters should be passed to Getchildfragmentmanager () Studyviewpager.setadapter (Madatpter); Tabpageindicator.setviewpager (Studyviewpager); }}
So, a major top navigation tab is out, and then we can define the tab style in the Style.xml file. We join:
<!--Remove the black edge of the tab top-<style name= "No_title" parent= "@android: Style/theme.light.notitlebar" > <item Name= "Android:windowcontentoverlay" > @null </item> </style> <style name= "MyTheme" parent= "No_title "> <item name=" Vpitabpageindicatorstyle "> @style/mywidget.tabpageindicator</item> <item nam E= "Android:windownotitle" >true</item> <item name= "Android:animationduration" >5000</item> <item name= "Android:windowcontentoverlay" > @null </item> </style> <style name= "Mywidget.tabpage Indicator "parent=" Widget "> <item name=" android:gravity ">center</item> <item name=" Android : Background "> @drawable/vpi__tab_indicator</item> <item name=" Android:paddingleft ">22dip</item& Gt <item name= "Android:paddingright" >22dip</item> <item name= "Android:paddingtop" >1dp</item> <item NamE= "Android:paddingbottom" >1dp</item> <item name= "android:textappearance" > @style/ mytextappearance.tabpageindicator</item> <item name= "android:textsize" >14sp</item> <ite M name= "Android:maxlines" >1</item> </style> <style name= "Mytextappearance.tabpageindicator" Paren t= "Widgets" > <item name= "android:textstyle" >bold</item> <item name= "Android:textcolor" ># 2c3e50</item> </style>
after the style is defined well. Simply configure the theme for the activity to:
<activity android:name= ". Mainactivity " android:label=" @string/app_name " android:theme=" @style/mytheme "> < intent-filter> <action android:name= "Android.intent.action.MAIN"/> <category android:name= " Android.intent.category.LAUNCHER "/> </intent-filter></activity>
Well, take a look at the effect:
How about that? Happy, you want the tab finally come out, you satisfied?
Please don't be satisfied. Because this tab is not stable, it also has loopholes, let's look at the following.
Iv. pits and solutions in tab navigation4.1 Fragment two times when loading the Oncreateview method will report an exception: Java.lang.IllegalStateException
For previously implemented tab navigation, when we switch tabs back and forth. Will find that the system will crash:
The error means that when you switch tab back to the fragment that you have already loaded. The system does not agree with the previous fragment when the view is loaded again without removing it, a view can have only one parent control . Please take a careful look at our Fragmentstudy code:
if (view==null) { view = inflater.inflate (R.layout.fragment_study, container, false);}
We have only one instance to guarantee. Only if it is null inferred, only one initialization is done.
So how do we fix it?
Someone said yes. It would be nice to remove the inference view==null directly.
。。 Well, really good, but have you ever considered creating a new view every time, wasting resource performance?
Well, how about that? Don't worry. There is a way. Let's Change the code:
Import Android.os.bundle;import Android.support.v4.app.fragment;import Android.view.layoutinflater;import Android.view.view;import Android.view.viewgroup;import Com.lidroid.xutils.viewutils;public class FragmentStudy Extends Fragment {private view view = NULL; @Override public void OnCreate (Bundle savedinstancestate) {//TODO auto-generated method stub super.oncr Eate (savedinstancestate);//pos = Getarguments (). GetInt ("pos");//System.out.println (POS); Layoutinflater inflater = getactivity (). Getlayoutinflater (); View = Inflater.inflate (R.layout.fragment_study, (ViewGroup) getactivity (). Findviewbyid (R.id.study_viewpager), FALSE); } @Override Public View oncreateview (layoutinflater inflater, ViewGroup container, Bundle savedinstancestate) {// if (view==null) {//view = Inflater.inflate (R.layout.fragment_study, container, false);//}// The sentence must be added viewgroup p = (viewgroup) view.getparent (); if (P! = null) {p.removeallviewsinlayout (); } viewutils.inject (this, view); return view; }}
did you find anything? Yes, the process of creating a view loaded into a layout file is placed in the OnCreate () method, which simply loads the layout the first time the fragment is created. After the switch, the layout is no longer loaded.
Beautiful Ah!!!
In the execution of the project, the discovery will not collapse again?!
4.2 Viewpager Pre-loading fragment recurring request problem
I do not know if you know, Viewpager has a function, also known as a viewpager advantage. Is that it can pre-load into the fragment. But suppose I have a network request in every fragment, wouldn't it be loading a fragment to send multiple requests? It's a bad experience. Is there any way to change it?
Some say. That's not easy. Set the Viewpager not to pre-load not just good!
Right. As simple as this, Viewpager does provide the corresponding method. To set the number of pre-loaded fragment:
Set by Viewpager's setoffscreenpagelimit (int pagenum), which by default is 1. For example Viewpager. Setoffscreenpagelimit (2) will preload 2 pages,Viewpager. Setoffscreenpagelimit (0) will not preload the page.
But, what a fucking thing, I tried. Viewpager . Setoffscreenpagelimit (0) This method is not practical at all, it really makes me crazy.
What should I do?
Google a bit. It really made me find a way to rewrite fragment's Setuservisiblehint method:
When using Fragment+viewpage, you will find that the settings setoffscreenpagelimit (0) do not pre-load the page, either//can be replaced by the method below. The next method is to make a copy of the method below on the sub-page (that is, fragment), infer whether the current page is based on whether fragment is visible, and then run the Network load data @Override public void Setuservisiblehint ( Boolean isvisibletouser) {super.setuservisiblehint (isvisibletouser); if (Isvisibletouser) {//fragment is visible, run load data or progress bar qrydatafromserver (); } else {//do not run when not visible}} private void Qrydatafromserver () {System.out.println ("+pos +" Fragment is Qrydatafromserver "); }
Come on, let's do the next project, Toggle tab. Look at the output:
I/system.out: No. 0 Fragment is qrydatafromserveri/system.out: 1th fragment is qrydatafromserveri/system.out: 2nd fragment is qrydatafromserveri/system.out: 3rd fragment are qrydatafromserveri/system.out: 2nd fragment is qrydatafromserveri/ System.out: 1th fragment is qrydatafromserveri/system.out: No. 0 fragment is Qrydatafromserver
This is the right way to switch to which fragment to make a network request instead of preloading multiple network requests at a time.
Summary:
I believe you can see here that you have mastered how to use Tabpageindicator and viewpager to develop a more perfect top navigation bar. In fact,Tabpageindicator is not difficult to use. The most important thing is to avoid some of the pits mentioned above. This will lead to a faster development efficiency.
Source code (FREE): http://download.csdn.net/detail/zuiwuyuan/9039533
Android Open source framework Viewpageindicator and viewpager for tab navigation