Android UI 详解之ActionBar+ViewPager+Fragment 实现滑动Tab
一、 ActionBar 可以实现Tab导航栏,但是我们只能通过点击每个Tab标题实现,也可是通过定义手势,触发切换的方法,但这种显然效果不好,而且实现起来复杂。在网上找了好久也都没给出果完整代码,今天就来总结一下。分享给大家
ViewPager用于实现多页面的切换效果.他相当于一个容器和ListView很像,
这里我们不过多介绍ActionBar和ViewPager的消息用法,我这里主要就是告诉大家如何实现此效果
二、下面看一下具体代码结构,然后我们在分析以下
看一下实际的代码
MainActivity.java
package com.sim.myTab;
import com.example.mytab.R;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.Activity;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.ActionMode;
//为了让低版本的api兼容,也就是minSdk小的情况
@SuppressLint("NewApi")
public class MainActivity extends Activity{
private static final String INSTANCESTATE_TAB = "tab";
private static final int DEFAULT_OFFSCREEN_PAGES =2;
private ViewPager viewPager;
private TabsAdapter tabsAdapter; //定义一个ViewPager需要的容器
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
viewPager = (ViewPager) findViewById(R.id.pager);
// 预告加载的页面数量,也就是会预先加载当前页的下两页
viewPager.setOffscreenPageLimit(DEFAULT_OFFSCREEN_PAGES);
final ActionBar bar = getActionBar();
//设置ActionBar使用Tab导航方式
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
//这个值改变会出现菜单栏
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE
| ActionBar.DISPLAY_SHOW_HOME);
/*
* 创建TabAdapter ,向Adapter中添加Fragment,并且添加监听器,
* 这里自己实现了监听器,并且为ViewPager添加此Adapter
*/
tabsAdapter = new TabsAdapter(MainActivity.this, viewPager);
tabsAdapter.addTab(bar.newTab().setText(R.string.cloc), Fragment1.class,
null);
tabsAdapter.addTab(bar.newTab().setText(R.string.alarm), Fragment2.class,
null);
tabsAdapter.addTab(bar.newTab().setText(R.string.timer), Fragment3.class,
null);
//指定默认打开的页面
bar.setSelectedNavigationItem(PreferenceManager
.getDefaultSharedPreferences(this).getInt(INSTANCESTATE_TAB, 1));
}
}
Fragment1.java
package com.sim.myTab;
import com.example.mytab.R;
import android.annotation.SuppressLint;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
@SuppressLint("NewApi")
public class Fragment1 extends Fragment{
TextView textView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View tab1= inflater.inflate(R.layout.tab1, container,false);
textView=(TextView) tab1.findViewById(R.id.textView1);
textView.setOnClickListener(new MyOnClickListener());
return tab1;
}
class MyOnClickListener implements OnClickListener{
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.textView1:
Toast.makeText(getActivity().getApplicationContext(), "点击了", 1).show();
break;
default:
break;
}
}
}
}
Fragment2.java
package com.sim.myTab;
import com.example.mytab.R;
import android.annotation.SuppressLint;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
@SuppressLint("NewApi")
public class Fragment2 extends Fragment {
TextView textView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View tab1= inflater.inflate(R.layout.tab1, container,false);
textView=(TextView) tab1.findViewById(R.id.textView1);
textView.setText("tab2");
return tab1;
}
}
Fragment3.java
package com.sim.myTab;
import com.example.mytab.R;
import android.annotation.SuppressLint;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
@SuppressLint("NewApi")
public class Fragment3 extends Fragment {
TextView textView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View tab1= inflater.inflate(R.layout.tab1, container,false);
textView=(TextView) tab1.findViewById(R.id.textView1);
textView.setText("tab3");
return tab1;
}
}
TabInfo.java
package com.sim.myTab;
import android.annotation.SuppressLint;
import android.app.Fragment;
import android.os.Bundle;
/**
* 定义每个Tab的信息
* @author qiyue
*
*/
@SuppressLint("NewApi")
public class TabInfo {
private final Class<?> clss;
private final Bundle args;
private Fragment fragment;
public Fragment getFragment() {
return fragment;
}
public void setFragment(Fragment fragment) {
this.fragment = fragment;
}
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
public Class<?> getClss() {
return clss;
}
public Bundle getArgs() {
return args;
}
}
TabsAdapter.java
package com.sim.myTab;
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.support.v13.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.ActionMode;
import com.example.mytab.R;
@SuppressLint("NewApi")
public class TabsAdapter extends FragmentPagerAdapter {
private Context context;
private ActionBar actionBar;
private ViewPager viewPager;
private final ArrayList<TabInfo> tabInfos = new ArrayList<TabInfo>();
public TabsAdapter(Activity activity, ViewPager pager) {
super(activity.getFragmentManager());
this.context = activity;
this.actionBar = activity.getActionBar();
this.viewPager = pager;
this.viewPager.setAdapter(this);
this.viewPager.setOnPageChangeListener(new OnPageChangeListener());
}
@Override
public Fragment getItem(int position) {
TabInfo tabInfo = tabInfos.get(position);
if (tabInfo.getFragment()==null){
tabInfo.setFragment(Fragment.instantiate(this.context
,tabInfo.getClss().getName(),tabInfo.getArgs()));
}
return tabInfo.getFragment();
}
@Override
public int getCount() {
return tabInfos.size();
}
/*
* tabsAdapter.addTab(bar.newTab().setText(R.string.cloc), Fragment1.class,null);
*/
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
//封装Tab信息
TabInfo info = new TabInfo(clss, args);
tabInfos.add(info);
tab.setTag(info);
//给tab添加监听
tab.setTabListener(new TabListener());
actionBar.addTab(tab);
notifyDataSetChanged();
}
//定义Page切换时的listener,给ViewPager加的
class OnPageChangeListener implements ViewPager.OnPageChangeListener{
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
}
//定义Tab的点击事件
class TabListener implements ActionBar.TabListener{
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
for (int i = 0; i < tabInfos.size(); i++) {
if (tabInfos.get(i) == tag) {
viewPager.setCurrentItem(i);
}
}
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
tab1.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:gravity="center"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="TextView" />
</LinearLayout>
从上面代码,我们分析以下思路,我们首先创建一个主布局文件main.xml 其中定义一个viewPager组件,我们在定义viewPager中要显示内容tab1.xml 这里就只有一个textview,然后取得ViewPager对象并且创建ActionBar对象,创建一个Adapter 类,在Adapter的构造方法中我们给ViewPager设置adapter,然后给viewpager添加页面切换事件,在adapter中添加一个add方法用来初始化数据,者个初始化数据是创建这个Adapter对象所需要的数据,也就是这个Adapter的构造方中需要的数据,实际上就是创建一个ActionBar的Tab,然后设置给tab设置点击时监听器。
然后我们看看他们的工作顺序,实际上我们事先ActionBar和ViewPager是独立的,这里只是在适当的时机去改变对方的状态,
也就是从ViewPager说起,当页面滑动时会触发onPageChangeListener,然后在这里面还需调用actionbar的方法,改变其状态,
,然后系统会调用getItem填充数据,这里getItem方法会根据前面设置有没有预加载,如果预加载了就不会调用,如果没有就会被调用。同理反过来也是用户点击ActionBar中tab,触发onTabSelected(),然后在这个里面根据tab包含的信息Tag判断是哪个页面来设置Viewpager中要显示的页面,最后调用相应的getItem()方法