首页 > 代码库 > TabLayout 和 ViewPager【综合示例】
TabLayout 和 ViewPager【综合示例】
完整Demo地址:https://github.com/baiqiantao/TabLayoutTest.git
MainActivity
public class MainActivity extends ListActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] array = {"0、不重写getPageTitle,会导致没有标题",
"1、使用默认的MODE_FIXED模式",
"2、代码中设置Tab样式",
"3、XML中设置Tab样式",
"4、和VP联动演示,自定义Tab,添加监听,自定义Tab间距",
"5、不自定义Tab,不添加监听,不自定义Tab间距(注意:这里tabMinWidth的默认值会严重影响Tab的宽度)",
"6、自定义Tab,添加监听,不自定义Tab间距",
"7、添加点击事件,但不手动处理点击Tab后TabLayout和VP的变化",
"8、添加点击事件,并手动处理点击Tab后TabLayout和VP的变化",
"9、【动态添加、删除VP中的数据--正常情况】",
"9、【动态添加、删除VP中的数据--非正常情况】",};
setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new ArrayList<>(Arrays.asList(array))));
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
switch (position) {
case 0:
case 1:
case 2:
case 3:
Intent intent = new Intent(this, Activity1.class);
intent.putExtra("tag", position);
startActivity(intent);
break;
case 4:
case 5:
case 6:
Intent intent2 = new Intent(this, Activity2.class);
intent2.putExtra("tag", position);
startActivity(intent2);
break;
case 7:
case 8:
Intent intent3 = new Intent(this, Activity3.class);
intent3.putExtra("tag", position);
startActivity(intent3);
break;
case 9:
Intent intent4 = new Intent(this, Activity_VP1.class);
intent4.putExtra("tag", position);
startActivity(intent4);
break;
case 10:
Intent intent5 = new Intent(this, Activity_VP2.class);
intent5.putExtra("tag", position);
startActivity(intent5);
break;
}
}
}
MyFragment
public class MyFragment extends Fragment {
public static MyFragment newInstance(String tag) {
Bundle args = new Bundle();
args.putString("tag", tag);
MyFragment fragment = new MyFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
TextView textView = new TextView(getContext());
textView.setText(getArguments().getString("tag"));
textView.setGravity(Gravity.CENTER);
textView.setBackgroundColor(0xFF000000 + new Random().nextInt(0xFFFFFF));
//注意,Integer.MAX_VALUE= http://www.mamicode.com/0x7fffffff,超过这个值就是负数了,所以通过随机数获取int值时,传入的值要小于0x7fffffff
return textView;
}
}
Activity1 样式
public class Activity1 extends FragmentActivity {
private List<String> list = new ArrayList<>(Arrays.asList(new String[]{"包青天", "白", "baiqiantao(注意大小写)", "1", "12", "123", "1234",}));
private int tag;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tag = getIntent().getIntExtra("tag", 0);
//3、XML中设置Tab样式
TabLayout tabLayout;
if (tag != 3) {
tabLayout = (TabLayout) findViewById(R.id.tablayout1);
findViewById(R.id.tablayout1).setVisibility(View.VISIBLE);
} else {
tabLayout = (TabLayout) findViewById(R.id.tablayout2);
findViewById(R.id.tablayout2).setVisibility(View.VISIBLE);
}
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return MyFragment.newInstance(list.get(position));
}
@Override
public int getCount() {
return list.size();
}
@Override
public CharSequence getPageTitle(int position) {
if (tag == 0) return super.getPageTitle(position);
//0、不重写ViewPager的getPageTitle方法,会导致TabLayout没有标题
else return list.get(position);//因为返回值是CharSequence,所以可以返回一个内容丰富的SpannableString
}
});
tabLayout.setupWithViewPager(viewPager);
//1、默认MODE_FIXED模式,会将每个tab都显示出来,tab的宽度一样;MODE_SCROLLABLE会根据tab中的内容自动调整tab宽度
if (tag != 1) tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
//2、代码中设置Tab样式
if (tag == 2) {
tabLayout.setTabGravity(Gravity.TOP);//没卵用啊!
tabLayout.setTabTextColors(Color.RED, Color.GREEN);
tabLayout.setSelectedTabIndicatorColor(Color.BLUE);
tabLayout.setSelectedTabIndicatorHeight(15);
tabLayout.setBackgroundColor(Color.YELLOW);
}
}
}
Activity2 样式
public class Activity2 extends FragmentActivity {
private List<String> list = new ArrayList<>(Arrays.asList(new String[]{"包青天", "白", "baiqiantao(注意大小写)", "1", "12", "123", "1234",}));
private TabLayout tabLayout;
private ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int tag = getIntent().getIntExtra("tag", 0);
initView();
if (tag != 5) {//是否自定义Tab,是否添加监听
setCustomTabView();
addOnTabSelectedListener();
}
if (tag != 6) {//是否自定义Tab间距
tabLayout.post(new Runnable() {
@Override
public void run() {
setIndicator(tabLayout, 1, 1);//必须在setupWithViewPager之后(数据确定后)才可以操作
}
});
}
}
private void initView() {
viewPager = (ViewPager) findViewById(R.id.view_pager);
tabLayout = (TabLayout) findViewById(R.id.tablayout1);
findViewById(R.id.tablayout1).setVisibility(View.VISIBLE);
PagerAdapter adapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return MyFragment.newInstance(list.get(position));
}
@Override
public int getCount() {
return list.size();
}
@Override
public CharSequence getPageTitle(int position) {
return list.get(position);
}
};
viewPager.setAdapter(adapter);
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);//可滚动模式,另一个是固定宽度模式
tabLayout.setupWithViewPager(viewPager);
}
/**
* 使用自定义的Tab,设置后要自己控制每个Tab的文字以及【默认】选中Tab的样式(比如默认第一个Tab要显示indicator等)
*/
private void setCustomTabView() {
tabLayout.setSelectedTabIndicatorHeight(0);
for (int i = 0; i < list.size(); i++) {//必须在setupWithViewPager之后(即被绑定VP的数据确定后)才可以操作
View view = LayoutInflater.from(this).inflate(R.layout.item_tab, null);
TextView tv_tab_name = (TextView) view.findViewById(R.id.tv_tab_name);
View line_indicator = view.findViewById(R.id.line_indicator);
tv_tab_name.setText(list.get(i));//控制每个Tab的文字
if (i == 0) {//控制默认选中Tab的样式
view.setSelected(true);//背景样式
line_indicator.setSelected(true);//指示器样式
} else {
view.setSelected(false);
line_indicator.setSelected(false);
}
TabLayout.Tab tab = tabLayout.getTabAt(i);//获得每一个tab
if (tab != null) tab.setCustomView(view);//给每一个tab设置view
}
}
/**
* 添加监听,当使用自定义的Tab时,要自己控制选中Tab【改变】时Tab的样式,以及ViewPager的当前Item
*/
private void addOnTabSelectedListener() {
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
if (tab.getCustomView() != null) {
tab.getCustomView().setSelected(true);//要自己控制选中Tab改变时Tab的样式
tab.getCustomView().findViewById(R.id.line_indicator).setSelected(true);
viewPager.setCurrentItem(tab.getPosition());//要自己控制ViewPager的当前Item
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
if (tab.getCustomView() != null) {
tab.getCustomView().setSelected(false);
tab.getCustomView().findViewById(R.id.line_indicator).setSelected(false);
}
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
/**
* 自定义Indicator左右间距。适用于自定义Tab的情况下,在使用默认Tab时,通过tabPadding设置既可以了
* 注意:除了tabPadding外,tabMinWidth的值也会影响Tab的宽度,特别是1-2两字符时,会非常明显
*/
public static void setIndicator(TabLayout tabs, int leftDip, int rightDip) {
try {
Class<?> tabLayout = tabs.getClass();
Field tabStrip = tabLayout.getDeclaredField("mTabStrip");
tabStrip.setAccessible(true);
int left = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, leftDip, Resources.getSystem().getDisplayMetrics());
int right = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, rightDip, Resources.getSystem().getDisplayMetrics());
LinearLayout llTab = (LinearLayout) tabStrip.get(tabs);
for (int i = 0; i < llTab.getChildCount(); i++) {
View child = llTab.getChildAt(i);
child.setPadding(0, 0, 0, 0);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1);
params.leftMargin = left;
params.rightMargin = right;
child.setLayoutParams(params);
child.invalidate();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Activity3 样式
public class Activity3 extends FragmentActivity implements View.OnClickListener {
private List<String> list = new ArrayList<>(Arrays.asList(new String[]{"包青天", "白", "baiqiantao(注意大小写)", "1", "12", "123", "1234",}));
private TabLayout tabLayout;
private ViewPager viewPager;
private int tag;
private static final int OFFSET = 10086;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tag = getIntent().getIntExtra("tag", 0);
initView();
setCustomTabView();
addOnTabSelectedListener();
tabLayout.post(new Runnable() {
@Override
public void run() {
setIndicator(tabLayout, 1, 1);//必须在setupWithViewPager之后(数据确定后)才可以操作
}
});
}
private void initView() {
viewPager = (ViewPager) findViewById(R.id.view_pager);
tabLayout = (TabLayout) findViewById(R.id.tablayout1);
findViewById(R.id.tablayout1).setVisibility(View.VISIBLE);
PagerAdapter adapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return MyFragment.newInstance(list.get(position));
}
@Override
public int getCount() {
return list.size();
}
@Override
public CharSequence getPageTitle(int position) {
return list.get(position);
}
};
viewPager.setAdapter(adapter);
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
tabLayout.setupWithViewPager(viewPager);
}
private void setCustomTabView() {
tabLayout.setSelectedTabIndicatorHeight(0);
for (int i = 0; i < list.size(); i++) {//必须在setupWithViewPager之后(数据确定后)才可以操作
View view = LayoutInflater.from(this).inflate(R.layout.item_tab, null);
//注意:给view添加点击事件后,点击Tab后的点击事件会被这里的view消耗掉,所以Tab自身的点击事件不会响应
//也即点击Tab后将不会触发OnTabSelectedListener,也不会自动切换VP,这些都需要我们自己手动处理
if (i <= 3) {
view.setTag(i + OFFSET);
view.setOnClickListener(this);
}
TextView tv_tab_name = (TextView) view.findViewById(R.id.tv_tab_name);
View line_indicator = view.findViewById(R.id.line_indicator);
tv_tab_name.setText(list.get(i));
if (i == 0) {
view.setSelected(true);
line_indicator.setSelected(true);
} else {
view.setSelected(false);
line_indicator.setSelected(false);
}
TabLayout.Tab tab = tabLayout.getTabAt(i);//获得每一个tab
if (tab != null) tab.setCustomView(view);//给每一个tab设置view
}
}
private void addOnTabSelectedListener() {
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
if (tab.getCustomView() != null) {
tab.getCustomView().setSelected(true);
tab.getCustomView().findViewById(R.id.line_indicator).setSelected(true);
viewPager.setCurrentItem(tab.getPosition());
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
if (tab.getCustomView() != null) {
tab.getCustomView().setSelected(false);
tab.getCustomView().findViewById(R.id.line_indicator).setSelected(false);
}
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
/**
* 自定义Indicator左右间距。适用于自定义Tab的情况下,在使用默认Tab时,通过tabPadding设置既可以了
* 注意:除了tabPadding外,tabMinWidth的值也会影响Tab的宽度,特别是1-2两字符时,会非常明显
*/
public static void setIndicator(TabLayout tabs, int leftDip, int rightDip) {
try {
Class<?> tabLayout = tabs.getClass();
Field tabStrip = tabLayout.getDeclaredField("mTabStrip");
tabStrip.setAccessible(true);
int left = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, leftDip, Resources.getSystem().getDisplayMetrics());
int right = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, rightDip, Resources.getSystem().getDisplayMetrics());
LinearLayout llTab = (LinearLayout) tabStrip.get(tabs);
for (int i = 0; i < llTab.getChildCount(); i++) {
View child = llTab.getChildAt(i);
child.setPadding(0, 0, 0, 0);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1);
params.leftMargin = left;
params.rightMargin = right;
child.setLayoutParams(params);
child.invalidate();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onClick(View v) {
if (tag != 7) {
int currentTabPosition = (int) v.getTag() - OFFSET;
if (currentTabPosition >= 0 && currentTabPosition < tabLayout.getTabCount()) {
reSetTabLayout(currentTabPosition);
//setCurrentItem时,当点击最边缘那个Tab后,TabLayout也会像之前那样,将被点击的那个Tab滚动到屏幕中间
viewPager.setCurrentItem(currentTabPosition);
}
}
Toast.makeText(this, "我们需要自己手动处理点击Tab后所有变化", Toast.LENGTH_SHORT).show();
}
private void reSetTabLayout(int currentTabPosition) {
for (int j = 0, count = tabLayout.getTabCount(); j < count; j++) {
TabLayout.Tab tab = tabLayout.getTabAt(j);
if (tab != null) {
View view = tab.getCustomView();
if (view != null) {
TextView tv_tab_name = (TextView) view.findViewById(R.id.tv_tab_name);
View line_indicator = view.findViewById(R.id.line_indicator);
tv_tab_name.setText(list.get(j));
if (j == currentTabPosition) {
view.setSelected(true);
line_indicator.setSelected(true);
} else {
view.setSelected(false);
line_indicator.setSelected(false);
}
}
}
}
}
}
Activity_VP1 样式
public class Activity_VP1 extends FragmentActivity {
/**
* 此Demo演示:不保存Fragment的引用,当adapter调用getItem时去【重新创建】新的Fragment
*/
private List<String> list = new ArrayList<>(Arrays.asList(new String[]{"白", "1", "2", "3", "4", "5", "6", "7", "8",}));
private PagerAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.tv_add).setVisibility(View.VISIBLE);
findViewById(R.id.tv_remove).setVisibility(View.VISIBLE);
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
//1、必须使用【FragmentStatePagerAdapter】,而不能使用FragmentPagerAdapter
adapter = new FragmentStatePagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return MyFragment.newInstance(list.get(position));//每次都是创建新的Fragment
}
@Override
public int getCount() {
return list.size();
}
//2、必须重写getItemPosition,并且返回【PagerAdapter.POSITION_NONE】
@Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
};
viewPager.setAdapter(adapter);
}
public void add(View view) {
list.add(0, new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault()).format(new Date()));
adapter.notifyDataSetChanged();
}
public void remove(View view) {
if (list.size() > 0) list.remove(0);
adapter.notifyDataSetChanged();
}
}
Activity_VP2 样式
public class Activity_VP2 extends FragmentActivity {
/**
* 此Demo演示:保存所有Fragment的引用,当adapter调用getItem时去【获取】已经创建的Fragment
*/
private List<Fragment> fragments;
private PagerAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.tv_add).setVisibility(View.VISIBLE);
findViewById(R.id.tv_remove).setVisibility(View.VISIBLE);
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
String[] array = new String[]{"baiqiantao", "白", "包青天", "白乾涛", "1", "2", "3", "4", "5", "6", "7", "8",};
fragments = new ArrayList<>();
for (String string : array) {
fragments.add(MyFragment.newInstance(string));
}
//1、必须使用【FragmentStatePagerAdapter】,而不能使用FragmentPagerAdapter
adapter = new FragmentStatePagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return fragments.get(position);//这里的Fragment都是已经创建好的,而不是getItem时重新创建的
}
@Override
public int getCount() {
return fragments.size();
}
//2、必须重写getItemPosition,并且返回【PagerAdapter.POSITION_NONE】
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
};
viewPager.setAdapter(adapter);
}
public void add(View view) {
String data = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault()).format(new Date());
fragments.add(0, MyFragment.newInstance(data));
setFragments(fragments);
}
public void remove(View view) {
if (fragments.size() > 0) fragments.remove(0);
setFragments(fragments);
}
public void setFragments(List<Fragment> fragments) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
for (Fragment f : fragments) {
ft.remove(f);
}
ft.commit();
getSupportFragmentManager().executePendingTransactions();
this.fragments = fragments;
adapter.notifyDataSetChanged();
}
}
XML布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_add"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/colorAccent"
android:gravity="center"
android:onClick="add"
android:text="添加一个Item"
android:visibility="gone"/>
<TextView
android:id="@+id/tv_remove"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/colorPrimary"
android:gravity="center"
android:onClick="remove"
android:text="移除一个Item"
android:visibility="gone"/>
<android.support.design.widget.TabLayout
android:id="@+id/tablayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
app:theme="@style/Widget.Design.TabLayout"/>
<android.support.design.widget.TabLayout
android:id="@+id/tablayout2"
style="@style/MyTabStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
app:tabTextAppearance="@style/MyTabTextAppearance"/>
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
自定义Tab的布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="50dp"
android:layout_height="35dp"
android:background="@drawable/sel_tab_bgcolor"
><TextView
android:id="@+id/tv_tab_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:ellipsize="end"
android:gravity="center"
android:maxEms="3"
android:maxLines="1"
android:text="热门热门热门热门"
android:textColor="@drawable/sel_tab_textcolor"
android:textSize="12sp"/>
<TextView
android:id="@+id/line_indicator"
android:layout_width="40dp"
android:layout_height="3dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/sel_tab_indicator"/>
</RelativeLayout>
选择器
sel_tab_textcolor
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#f00" android:state_selected="true"/>
<item android:color="#00f"/>
</selector>
sel_tab_bgcolor 和 sel_tab_indicator
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<shape>
<corners android:radius="2dp"/>
<solid android:color="#f00"/>
</shape>
</item>
<item>
<shape>
<corners android:radius="2dp"/>
<solid android:color="#00f"/>
</shape>
</item>
</selector>
定义的样式
<style name="MyTabStyle" parent="Widget.Design.TabLayout">
<item name="android:background">@android:color/holo_green_dark</item><!--此背景会被tabBackground覆盖掉-->
<item name="tabBackground">@android:color/holo_orange_dark</item><!--"通常"和background的效果完全一样-->
<item name="tabContentStart">20dp</item><!--此值导致左边一块区域属于background,但不属于tabBackground-->
<item name="tabGravity">fill</item><!--只能是fill或center,貌似没有卵用啊-->
<item name="tabIndicatorHeight">5dp</item>
<item name="tabIndicatorColor">#f00</item>
<item name="tabMaxWidth">120dp</item>
<item name="tabMinWidth">20dp</item>
<item name="tabPadding">0dp</item>
<item name="tabMode">scrollable</item>
<item name="tabSelectedTextColor">#f00</item>
<!--以下属性貌似都无效!-->
<item name="android:ellipsize">end</item>
<item name="android:maxLines">1</item>
<item name="android:gravity">top</item>
<item name="android:textColor">#fff</item>
</style>
<style name="MyTabTextAppearance" parent="TextAppearance.Design.Tab"><!--必须继承自TextAppearance.Design.Tab -->
<!--只支持以下三个属性-->
<item name="android:textSize">15sp</item>
<item name="android:textAllCaps">false</item>
<!--选择器无效!除非根据tab的选中状态手动设置-->
<item name="android:textColor">@drawable/sel_tab_textcolor</item>
</style>
2017-6-28
null
TabLayout 和 ViewPager【综合示例】
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。