自定义TabBarView,快速实现Tab+ViewPager的Activity
2017-05-24 17:21
483 查看
先来看两个Activity的页面效果:
这两个Activity页面的实现代码分别为:
HomeWithTabActivity.java
OrderListWithTabActivity.java
看起来,两者的代码几乎是一模一样的,唯一不同的就是他们各自的xmlLayout布局文件不同。
接下来我们来看看具体是怎么实现的。
首先介绍一下我们的自定义标签栏
TabBarView.java
再来看看它的API:
public class TabBarView extends LinearLayout
注意事项:
1. setTabItemViews() 方法不可重复调用。
2. 如果需要有一个子超出父布局位置限制的centerView的话,需要在TabBarView的父布局xml中添加属性 android:clipChildren=”false”。
接下来,看一看用TabBarView+ViewPager封装的一个抽象的Activity
TabWithViewPagerBaseActivity.java
看看它的API:
public abstract class TabWithViewPagerBaseActivity extends AppCompatActivity
注意事项:
1. 你的Activity的onCreat()方法中不能调用setContentView(int resLayout)方法,xmlLayout必须由getContentLayout()方法提供。
2. 由getContentLayout()方法提供的xml布局文件中必须得至少包含一个id为R.id.tabBarView的TabBarView和一个id为R.id.viewpager的ViewPager。
3. getTabViews()和getFragments()分别提供的集合的长度必须一致。
这两个Activity页面的实现代码分别为:
HomeWithTabActivity.java
package zou.zohar.tabbarview.activity; import android.os.Bundle; import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.view.View; import android.widget.ImageView; import java.util.ArrayList; import java.util.List; import zou.zohar.tabbarview.R; import zou.zohar.tabbarview.fragment.TabFragment1; import zou.zohar.tabbarview.fragment.TabFragment2; import zou.zohar.tabbarview.fragment.TabFragment3; import zou.zohar.tabbarview.fragment.TabFragment4; import zou.zohar.tabbarview.widge.TabBarView; public class HomeWithTabActivity extends TabWithViewPagerBaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public TabBarView.ItemStyle getItemStyle() { return TabBarView.ItemStyle.ICON_TEXT; } @Override public List<TabBarView.TabItemView> getTabViews() { List<TabBarView.TabItemView> tabItemViews = new ArrayList<>(); tabItemViews.add(new TabBarView.TabItemView(this, "标题1", R.color.colorPrimary, R.color.colorAccent, R.mipmap.ic_launcher, R.mipmap.ic_launcher_deep)); tabItemViews.add(new TabBarView.TabItemView(this, "标题2", R.color.colorPrimary, R.color.colorAccent, R.mipmap.ic_launcher, R.mipmap.ic_launcher_deep)); tabItemViews.add(new TabBarView.TabItemView(this, "标题3", R.color.colorPrimary, R.color.colorAccent, R.mipmap.ic_launcher, R.mipmap.ic_launcher_deep)); tabItemViews.add(new TabBarView.TabItemView(this, "标题4", R.color.colorPrimary, R.color.colorAccent, R.mipmap.ic_launcher, R.mipmap.ic_launcher_deep)); return tabItemViews; } @Override public List<Fragment> getFragments() { List<Fragment> fragments = new ArrayList<>(); fragments.add(new TabFragment1()); fragments.add(new TabFragment2()); fragments.add(new TabFragment3()); fragments.add(new TabFragment4()); return fragments; } @Override public View getCenterView() { ImageView imageView = new ImageView(this); imageView.setImageResource(R.mipmap.ic_launcher_round); imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Snackbar.make(v, "center view click", Snackbar.LENGTH_SHORT).show(); } }); return imageView; } @Override public int getContentLayout() { return R.layout.activity_home_with_tab; } }
OrderListWithTabActivity.java
package zou.zohar.tabbarview.activity; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.View; import java.util.ArrayList; import java.util.List; import zou.zohar.tabbarview.R; import zou.zohar.tabbarview.fragment.TabFragment1; import zou.zohar.tabbarview.fragment.TabFragment2; import zou.zohar.tabbarview.fragment.TabFragment3; import zou.zohar.tabbarview.fragment.TabFragment4; import zou.zohar.tabbarview.widge.TabBarView; public class OrderListWithTabActivity extends TabWithViewPagerBaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public TabBarView.ItemStyle getItemStyle() { return TabBarView.ItemStyle.TEXT; } @Override public List<TabBarView.TabItemView> getTabViews() { List<TabBarView.TabItemView> tabItemViews = new ArrayList<>(); tabItemViews.add(new TabBarView.TabItemView(this, "已完成", R.color.colorPrimary, R.color.colorAccent, R.mipmap.ic_launcher, R.mipmap.ic_launcher_deep)); tabItemViews.add(new TabBarView.TabItemView(this, "未付款", R.color.colorPrimary, R.color.colorAccent, R.mipmap.ic_launcher, R.mipmap.ic_launcher_deep)); tabItemViews.add(new TabBarView.TabItemView(this, "待收货", R.color.colorPrimary, R.color.colorAccent, R.mipmap.ic_launcher, R.mipmap.ic_launcher_deep)); tabItemViews.add(new TabBarView.TabItemView(this, "待评价", R.color.colorPrimary, R.color.colorAccent, R.mipmap.ic_launcher, R.mipmap.ic_launcher_deep)); return tabItemViews; } @Override public List<Fragment> getFragments() { List<Fragment> fragments = new ArrayList<>(); fragments.add(new TabFragment1()); fragments.add(new TabFragment2()); fragments.add(new TabFragment3()); fragments.add(new TabFragment4()); return fragments; } @Override public View getCenterView() { return null; } @Override public int getContentLayout() { return R.layout.activity_order_list_with_tab; } }
看起来,两者的代码几乎是一模一样的,唯一不同的就是他们各自的xmlLayout布局文件不同。
接下来我们来看看具体是怎么实现的。
首先介绍一下我们的自定义标签栏
TabBarView.java
package zou.zohar.tabbarview.widge; import android.content.Context; import android.content.res.TypedArray; import android.support.annotation.NonNull; import android.support.v4.content.ContextCompat; import android.util.AttributeSet; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import java.util.ArrayList; import java.util.List; import zou.zohar.tabbarview.R; public class TabBarView extends LinearLayout { /** * attribute * centerView的bottomMargin */ private int childrenBottomMargin; /** * tabItemView的展示样式 * 默认为 ICON_TEXT */ private ItemStyle mItemStyle = ItemStyle.ICON_TEXT; /** * 最新选择的item的position,-1表示没有选择任何一个 */ private int mCheckedPos = -1; /** * tabItemViews集合 */ private List<TabItemView> mTabItemViewList; public TabBarView(Context context) { super(context); init(); } public TabBarView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.TabItemView); childrenBottomMargin = attributes.getInt(R.styleable.TabItemView_childrenBottomMargin, 40); attributes.recycle(); init(); } private void init() { mTabItemViewList = new ArrayList<>(); } public void setItemStyle(@NonNull ItemStyle itemStyle) { this.mItemStyle = itemStyle; } public void setTabItemViews(@NonNull List<TabItemView> tabItemViews) { setTabItemViews(tabItemViews, null); } public void setTabItemViews(@NonNull List<TabItemView> tabItemViewList, View centerView) { /** * 不能重复设置mTabItemViewList */ if (mTabItemViewList.size() != 0) { throw new RuntimeException("mTabItemViewList cannot be repeated!"); } mTabItemViewList.addAll(tabItemViewList); if (mTabItemViewList.size() < 2) { throw new RuntimeException("The length of mTabItemViewList must not be less than 2!"); } for (int i = 0; i < mTabItemViewList.size(); i++) { if (centerView != null && i == mTabItemViewList.size() / 2) { /** * 给centerView设置childrenBottomMargin属性 */ LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); layoutParams.height = this.getLayoutParams().height + childrenBottomMargin; layoutParams.bottomMargin = childrenBottomMargin; layoutParams.gravity = Gravity.BOTTOM; centerView.setLayoutParams(layoutParams); this.addView(centerView); } final TabItemView tabItemView = mTabItemViewList.get(i); tabItemView.setItemStyle(mItemStyle == ItemStyle.ICON || mItemStyle == ItemStyle.ICON_TEXT, mItemStyle == ItemStyle.TEXT || mItemStyle == ItemStyle.ICON_TEXT); this.addView(tabItemView); final int currentItemPos = i; tabItemView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (currentItemPos == mCheckedPos) { return; } check(currentItemPos); } }); } /** * 舒适化所有的tabItemView */ for (TabItemView tab : mTabItemViewList) { tab.setStatus(TabItemView.STATE_DEFAULT); } /** * 默认选中第一个 */ check(0); } /** * 通过position的选择设置tabItemView的标识,使用-1作为清除标识的选择 * * @param position tabItemView在TabBarView中的序号 */ public void check(int position) { if (position != -1 && position == mCheckedPos) { return; } if (mCheckedPos != -1) { mTabItemViewList.get(mCheckedPos).setStatus(TabItemView.STATE_DEFAULT); } if (position != -1) { mTabItemViewList.get(position).setStatus(TabItemView.STATE_CHECKED); } setCheckedPos(position); } private void setCheckedPos(int checkedPos) { mCheckedPos = checkedPos; if (mOnCheckedChangeListener != null) { mOnCheckedChangeListener.onCheckedChanged(this, mCheckedPos); } } public TabItemView getCheckedTabItemView() { return mTabItemViewList.get(mCheckedPos); } private OnCheckedChangeListener mOnCheckedChangeListener; /** * 注册一个回调函数,用来检查选项卡的选项更改 * * @param listener the callback to call on checke dcca d state change */ public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { mOnCheckedChangeListener = listener; } public interface OnCheckedChangeListener { /** * <p>Called when the checked tab item has changed. When the * selection is cleared, checkedId is -1.</p> * * @param tabBarView the tabBarView in which the checked tab item has changed * @param checkedPos the position of the newly checked tab item */ void onCheckedChanged(TabBarView tabBarView, int checkedPos); } public enum ItemStyle { ICON, TEXT, ICON_TEXT } /** * ItemView */ public static class TabItemView extends LinearLayout { /** * 状态: checked and default */ public final static int STATE_DEFAULT = 1; public final static int STATE_CHECKED = 2; /** * 标题:tabItemView上显示的文字 */ public String title; /** * 标题的颜色: checked and default */ public int colorDef; public int colorChecked; /** * 图标: checked and default */ public int iconResDef; public int iconResChecked; public ImageView ivIcon; public TextView tvTitle; public TabItemView(Context context, String title, int colorDef, int colorChecked, int iconResDef, int iconResChecked) { super(context); this.title = title; this.colorDef = colorDef; this.colorChecked = colorChecked; this.iconResDef = iconResDef; this.iconResChecked = iconResChecked; init(); } public void init() { View view = LayoutInflater.from(super.getContext()).inflate(R.layout.view_tab_item, this); ivIcon = (ImageView) view.findViewById(R.id.ivIcon); tvTitle = (TextView) view.findViewById(R.id.tvTitle); LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); layoutParams.weight = 1; view.setLayoutParams(layoutParams); tvTitle.setText(title); } protected void setItemStyle(boolean showIcon, boolean showTitle) { ivIcon.setVisibility(showIcon ? VISIBLE : GONE); tvTitle.setVisibility(showTitle ? VISIBLE : GONE); } /** * 设置itemView的状态 */ public void setStatus(int status) { ivIcon.setImageResource(status == STATE_CHECKED ? iconResChecked : iconResDef); tvTitle.setTextColor(ContextCompat.getColor(super.getContext(), status == STATE_CHECKED ? colorChecked : colorDef)); } } }
再来看看它的API:
public class TabBarView extends LinearLayout
Nested classes | |
---|---|
enum | TabBarView.ItemStyle Item的展示样式枚举,有三种样式:ICON, TEXT, ICON_TEXT |
interface | TabBarView.OnCheckedChangeListener点击Item切换tab时的回调 |
class | TabBarView.TabItemView ItemView,继承至LinearLayout |
XML added attributes | |
---|---|
childrenBottomMargin | centerView相对于TabBarView的底部外边距,默认为40。eg.childrenBottomMargin="40" |
Public methods | |
---|---|
void | setItemStyle(@NonNull ItemStyle itemStyle) 设置tabItemView的展示样式 |
void | setTabItemViews(@NonNull List<TabItemView> tabItemViews) 设置tabItemView集合 |
void | setTabItemViews(@NonNull List<TabItemView> tabItemViewList, View centerView) 设置tabItemView集合和centerView |
void | void check(int position) 切换选中的tabItemView |
TabItemView | getCheckedTabItemView() 返回当前选中的tabItemView |
void | setOnCheckedChangeListener(OnCheckedChangeListener listener) 设置切换tabItemView时的回调接口 |
1. setTabItemViews() 方法不可重复调用。
2. 如果需要有一个子超出父布局位置限制的centerView的话,需要在TabBarView的父布局xml中添加属性 android:clipChildren=”false”。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/apk/res-auto" android:id="@+id/activity_home_with_tab" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false"> <zou.zohar.tabbarview.widge.TabBarView android:id="@+id/tabBarView" android:layout_width="match_parent" android:layout_height="46dp" tools:childrenBottomMargin="40" /> </RelativeLayout>
接下来,看一看用TabBarView+ViewPager封装的一个抽象的Activity
TabWithViewPagerBaseActivity.java
package zou.zohar.tabbarview.activity; import android.os.Bundle; import android.support.annotation.LayoutRes; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.view.View; import java.util.List; import zou.zohar.tabbarview.R; import zou.zohar.tabbarview.widge.TabBarView; /** * Created by zohar on 2017/5/21. * 抽象的含TabBarView和ViewPager的Activity */ public abstract class TabWithViewPagerBaseActivity extends AppCompatActivity { private TabBarView tabBarView; private ViewPager viewPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(getContentLayout()); tabBarView = (TabBarView) findViewById(R.id.tabBarView); viewPager = (ViewPager) findViewById(R.id.viewPager); viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) { @Override public Fragment getItem(int position) { return getFragments().get(position); } @Override public int getCount() { return getFragments().size(); } }); tabBarView.setItemStyle(getItemStyle() != null ? getItemStyle() : TabBarView.ItemStyle.ICON_TEXT); tabBarView.setTabItemViews(getTabViews(), getCenterView()); tabBarView.setOnCheckedChangeListener(new TabBarView.OnCheckedChangeListener() { @Override public void onCheckedChanged(TabBarView tabBarView, int checkedPos) { viewPager.setCurrentItem(checkedPos); } }); viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { tabBarView.check(position); } @Override public void onPageScrollStateChanged(int state) { } }); } /** * @return 返回tabItemView的展示样式 ( ICON, TEXT, ICON_TEXT) */ public abstract TabBarView.ItemStyle getItemStyle(); public abstract List<TabBarView.TabItemView> getTabViews(); public abstract List<Fragment> getFragments(); public abstract View getCenterView(); /** * @return 返回xml布局文件 */ public abstract @LayoutRes int getContentLayout(); }
看看它的API:
public abstract class TabWithViewPagerBaseActivity extends AppCompatActivity
Abstract methods | |
---|---|
TabBarView.ItemStyle | getItemStyle() 返回tabItemView的展示样式 |
List | getTabViews() 提供tabItemView的集合,不可返回null |
List< Fragment> | getFragments() 提供Fragment的集合,不可返回null |
View | getCenterView() 提供一个中间按钮,可返回null |
int | getContentLayout() 提供xml布局文件 |
1. 你的Activity的onCreat()方法中不能调用setContentView(int resLayout)方法,xmlLayout必须由getContentLayout()方法提供。
2. 由getContentLayout()方法提供的xml布局文件中必须得至少包含一个id为R.id.tabBarView的TabBarView和一个id为R.id.viewpager的ViewPager。
3. getTabViews()和getFragments()分别提供的集合的长度必须一致。
相关文章推荐
- [转]用Fragment+ViewPager+Tab实现快速导航
- ActionBar和Fragment结合ViewPager实现TabActivity
- 低版本系统兼容的ActionBar(六)用Fragment+ViewPager+Tab实现快速导航
- 自定义tab,viewpager实现仿tablayout切换效果
- 自定义的带tab的可左右滑动的viewpager之一 简单实现
- 首页-底部&顶部Tab导航(菜单栏)的实现:TabLayout+ViewPager+Fragment
- TabLayout、ViewPager、FragmentPagerAdapter实现新闻导航栏
- TabLayout + ViewPager 实现 页面滑动
- ViewPager+TabLayout快速集成底部Tab栏+Fragment
- android里面自定义View实现调用activity的方法怎么做
- Android自定义控件系列五:自定义ViewGroup(一)实现ViewPager效果
- TabLayout+ViewPager+Fragment实现懒加载
- android ViewPager实现的轮播图广告自定义视图,网络获取图片和数据
- Android零基础入门第69节:ViewPager快速实现引导页
- ViewPager实现简单Tab切换效果
- ViewPager+Fragment实现TabHost,Fragment动态添加、删除,Tab选项卡跟随滑动
- 利用ViewPager工具类,实现Tab指示器滑动页面
- Android零基础入门第69节:ViewPager快速实现引导页
- 使用TabLayout、ViewPager和Fragment实现顶部菜单可滑动切换
- Android开发之ViewPager实现轮播图(轮播广告)效果的自定义View