├── README.md
└── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
├── androidTest
└── java
│ └── com
│ └── chenxi
│ └── tabview
│ └── ExampleInstrumentedTest.java
├── main
├── AndroidManifest.xml
├── java
│ └── com
│ │ └── chenxi
│ │ └── tabview
│ │ ├── MainActivity.java
│ │ ├── TabFragment1.java
│ │ ├── TabFragment2.java
│ │ ├── TabFragment3.java
│ │ ├── TabFragment4.java
│ │ ├── TabFragment5.java
│ │ ├── adapter
│ │ ├── BaseAdapter.java
│ │ ├── MainViewAdapter.java
│ │ └── TabViewPagerAdapter.java
│ │ ├── listener
│ │ └── OnTabSelectedListener.java
│ │ ├── tools
│ │ └── DisplayUtil.java
│ │ └── widget
│ │ ├── Tab.java
│ │ ├── TabContainerView.java
│ │ └── TabHost.java
└── res
│ ├── drawable
│ └── common_red_round.xml
│ ├── layout
│ ├── activity_main_container.xml
│ ├── fragment_tab_1.xml
│ ├── fragment_tab_2.xml
│ ├── fragment_tab_3.xml
│ ├── fragment_tab_4.xml
│ └── fragment_tab_5.xml
│ ├── mipmap-xhdpi
│ └── elep_icon.png
│ ├── mipmap-xxhdpi
│ ├── elep_icon.png
│ ├── new_find_icon.png
│ ├── new_find_icon_grey.png
│ ├── new_finial_icon.png
│ ├── new_fininal_icon_grey.png
│ ├── new_life_icon.png
│ ├── new_life_icon_grey.png
│ ├── new_myhome_icon.png
│ ├── new_myhome_icon_grey.png
│ ├── new_shoppingcar_icon.png
│ └── new_shoppingcar_icon_grey.png
│ └── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── ids.xml
│ ├── strings.xml
│ └── styles.xml
└── test
└── java
└── com
└── chenxi
└── tabview
└── ExampleUnitTest.java
/README.md:
--------------------------------------------------------------------------------
1 | ## TabView
2 | >针对APP的首页出现频次比较高的界面,封装了底部导航栏切换效果的工具类,使用非常方便简洁。
3 |
4 | #### Demo展示
5 | [demo gif](https://raw.githubusercontent.com/Louis2014/MarkdownPhotos/master/photos/tabview.gif),详细分析请查看我的[简书博客](http://www.jianshu.com/u/ffe0b1acd89d)
6 |
7 | ### 一、功能介绍
8 | 1.支持滑动切换栏目。
9 | 2.支持底部导航按钮自定义样式。
10 | 3.支持导航按钮出现红点样式的消息提示。
11 |
12 | ### 二、使用方法
13 | * 布局中引用
14 |
15 | ```xml
16 |
28 | ```
29 | * ACTIVITY中引用
30 |
31 | ```java
32 | TabContainerView tabContainerView = (TabContainerView) findViewById(R.id.tab_container);
33 | MainViewAdapter mainViewAdapter=new MainViewAdapter(getSupportFragmentManager(),
34 | new Fragment[] {new TabFragment1(), new TabFragment2(),new TabFragment3(), new TabFragment4(),new TabFragment5()});
35 | mainViewAdapter.setHasMsgIndex(5);
36 | tabContainerView.setAdapter(mainViewAdapter);
37 | tabContainerView.setOnTabSelectedListener(new OnTabSelectedListener() {
38 | @Override
39 | public void onTabSelected(Tab tab) {
40 |
41 | }
42 | });
43 | ```
44 | * 布局自定义属性介绍
45 |
46 | ```
47 | tabTextSize:导航按钮字体大小
48 | drawablePadding:导航图片与文字的间距
49 | iconHeight: 导航图标高度
50 | iconWidth:导航图标宽度
51 | divideLineColor:导航栏顶部分割线颜色
52 | divideLineHeight:导航栏顶部分割线高度
53 | ```
54 | * 设置消息提醒(**导航按钮旁边的红色圆点**)
55 |
56 | ```
57 | setHasMsgIndex(5); //第五个导航按钮有消息提醒
58 | ```
59 |
60 |
61 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 | defaultConfig {
7 | applicationId "com.chenxi.tabview"
8 | minSdkVersion 14
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
25 | exclude group: 'com.android.support', module: 'support-annotations'
26 | })
27 | compile 'com.android.support:appcompat-v7:25.3.1'
28 | compile 'com.android.support.constraint:constraint-layout:1.0.2'
29 | testCompile 'junit:junit:4.12'
30 | }
31 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/chengxi/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/chenxi/tabview/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.chenxi.tabview", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chenxi/tabview/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v4.app.Fragment;
6 | import android.support.v7.app.AppCompatActivity;
7 |
8 | import com.chenxi.tabview.adapter.MainViewAdapter;
9 | import com.chenxi.tabview.listener.OnTabSelectedListener;
10 | import com.chenxi.tabview.widget.Tab;
11 | import com.chenxi.tabview.widget.TabContainerView;
12 |
13 | public class MainActivity extends AppCompatActivity {
14 |
15 | @Override
16 | protected void onCreate(@Nullable Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 | setContentView(R.layout.activity_main_container);
19 | TabContainerView tabContainerView = (TabContainerView) findViewById(R.id.tab_container);
20 | MainViewAdapter mainViewAdapter=new MainViewAdapter(getSupportFragmentManager(),
21 | new Fragment[] {new TabFragment1(), new TabFragment2(),new TabFragment3(), new TabFragment4(),new TabFragment5()});
22 | mainViewAdapter.setHasMsgIndex(5);
23 | tabContainerView.setAdapter(mainViewAdapter);
24 | tabContainerView.setOnTabSelectedListener(new OnTabSelectedListener() {
25 | @Override
26 | public void onTabSelected(Tab tab) {
27 |
28 | }
29 | });
30 |
31 |
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chenxi/tabview/TabFragment1.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview;
2 |
3 |
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.Fragment;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 | /**
12 | * Created by chengxi on 17/4/26.
13 | */
14 | public class TabFragment1 extends Fragment {
15 |
16 | @Nullable
17 | @Override
18 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
19 |
20 | return inflater.inflate(R.layout.fragment_tab_1, null);
21 |
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chenxi/tabview/TabFragment2.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v4.app.Fragment;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | /**
11 | * Created by chengxi on 17/4/26.
12 | */
13 | public class TabFragment2 extends Fragment{
14 | @Nullable
15 | @Override
16 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
17 |
18 | return inflater.inflate(R.layout.fragment_tab_2, null);
19 |
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chenxi/tabview/TabFragment3.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview;
2 | import android.os.Bundle;
3 | import android.support.annotation.Nullable;
4 | import android.support.v4.app.Fragment;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 |
10 | /**
11 | * Created by chengxi on 17/4/26.
12 | */
13 | public class TabFragment3 extends Fragment{
14 | @Nullable
15 | @Override
16 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
17 |
18 | return inflater.inflate(R.layout.fragment_tab_3, null);
19 |
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chenxi/tabview/TabFragment4.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview;
2 | import android.os.Bundle;
3 | import android.support.annotation.Nullable;
4 | import android.support.v4.app.Fragment;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 |
10 | /**
11 | * Created by chengxi on 17/4/26.
12 | */
13 | public class TabFragment4 extends Fragment{
14 |
15 | @Nullable
16 | @Override
17 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
18 |
19 | return inflater.inflate(R.layout.fragment_tab_4, null);
20 |
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chenxi/tabview/TabFragment5.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview;
2 | import android.os.Bundle;
3 | import android.support.annotation.Nullable;
4 | import android.support.v4.app.Fragment;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 |
10 | /**
11 | * Created by chengxi on 17/4/26.
12 | */
13 | public class TabFragment5 extends Fragment{
14 |
15 | @Nullable
16 | @Override
17 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
18 |
19 | return inflater.inflate(R.layout.fragment_tab_5, null);
20 |
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chenxi/tabview/adapter/BaseAdapter.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview.adapter;
2 |
3 | import android.support.v4.app.Fragment;
4 | import android.support.v4.app.FragmentManager;
5 |
6 | /**
7 | * Created by chengxi on 17/4/26.
8 | */
9 | public abstract class BaseAdapter {
10 |
11 | /**
12 | * tab数量
13 | */
14 | public abstract int getCount();
15 | public abstract int hasMsgIndex();
16 | /**
17 | * tab text 数组
18 | */
19 | public abstract String[] getTextArray();
20 |
21 | /**
22 | * tab icon 数组
23 | */
24 | public abstract int[] getIconImageArray();
25 |
26 | /**
27 | * tab icon 选中 数组
28 | */
29 | public abstract int[] getSelectedIconImageArray();
30 |
31 | /**
32 | * fragment 数组
33 | */
34 | public abstract Fragment[] getFragmentArray();
35 |
36 | public abstract FragmentManager getFragmentManager();
37 |
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chenxi/tabview/adapter/MainViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview.adapter;
2 |
3 | import android.support.v4.app.Fragment;
4 | import android.support.v4.app.FragmentManager;
5 |
6 | import com.chenxi.tabview.R;
7 |
8 | /**
9 | * Created by chengxi on 17/4/26.
10 | */
11 | public class MainViewAdapter extends BaseAdapter {
12 |
13 | private Fragment[] fragmentArray;
14 | private FragmentManager fragmentManager;
15 | private int hasMsgIndex=0;
16 |
17 | public void setHasMsgIndex(int hasMsgIndex) {
18 | this.hasMsgIndex = hasMsgIndex;
19 | }
20 |
21 | public MainViewAdapter(FragmentManager fragmentManager, Fragment[] fragmentArray) {
22 | this.fragmentManager = fragmentManager;
23 | this.fragmentArray = fragmentArray;
24 | }
25 |
26 | @Override
27 | public int getCount() {
28 | return 5;
29 | }
30 |
31 | @Override
32 | public int hasMsgIndex() {
33 | return hasMsgIndex;
34 | }
35 |
36 |
37 | @Override
38 | public String[] getTextArray() {
39 | return new String[] {"首页", "分类", "惊喜", "购物车","我的"};
40 | }
41 |
42 | @Override
43 | public Fragment[] getFragmentArray() {
44 | return fragmentArray;
45 | }
46 |
47 | @Override
48 | public int[] getIconImageArray() {
49 | return new int[] {R.mipmap.new_life_icon_grey, R.mipmap.new_find_icon_grey, R.mipmap.new_fininal_icon_grey, R.mipmap.new_shoppingcar_icon_grey,R.mipmap.new_myhome_icon_grey};
50 | }
51 |
52 | @Override
53 | public int[] getSelectedIconImageArray() {
54 | return new int[] {R.mipmap.new_life_icon, R.mipmap.new_find_icon, R.mipmap.new_finial_icon, R.mipmap.new_shoppingcar_icon,R.mipmap.new_myhome_icon};
55 | }
56 |
57 | @Override
58 | public FragmentManager getFragmentManager() {
59 | return fragmentManager;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chenxi/tabview/adapter/TabViewPagerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview.adapter;
2 |
3 | import android.support.v4.app.Fragment;
4 | import android.support.v4.app.FragmentManager;
5 | import android.support.v4.app.FragmentPagerAdapter;
6 |
7 |
8 | public class TabViewPagerAdapter extends FragmentPagerAdapter {
9 |
10 | private Fragment[] fragmentArray;
11 |
12 | public TabViewPagerAdapter(FragmentManager mFragmentManager, Fragment[] fragmentArray) {
13 | super(mFragmentManager);
14 | this.fragmentArray = fragmentArray;
15 | }
16 |
17 |
18 | @Override
19 | public Fragment getItem(int position) {
20 | return fragmentArray[position];
21 | }
22 |
23 | @Override
24 | public int getCount() {
25 | return fragmentArray.length;
26 | }
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chenxi/tabview/listener/OnTabSelectedListener.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview.listener;
2 |
3 |
4 | import com.chenxi.tabview.widget.Tab;
5 |
6 | /**
7 | * Created by chengxi on 17/4/26.
8 | */
9 | public interface OnTabSelectedListener {
10 |
11 | void onTabSelected(Tab tab);
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chenxi/tabview/tools/DisplayUtil.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview.tools;
2 |
3 | import android.content.Context;
4 |
5 | public class DisplayUtil {
6 |
7 | /**
8 | * 将dip或dp值转换为px值,保证尺寸大小不变
9 | *
10 | * @param dipValue
11 | * @return
12 | */
13 | public static int dip2px(Context context, float dipValue) {
14 | final float scale = context.getResources().getDisplayMetrics().density;
15 | return (int) (dipValue * scale + 0.5f);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chenxi/tabview/widget/Tab.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview.widget;
2 |
3 | import android.content.Context;
4 | import android.util.TypedValue;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.ImageView;
8 | import android.widget.LinearLayout;
9 | import android.widget.RelativeLayout;
10 | import android.widget.TextView;
11 |
12 | import com.chenxi.tabview.R;
13 | import com.chenxi.tabview.listener.OnTabSelectedListener;
14 |
15 | /**
16 | * Created by chengxi on 17/4/26.
17 | */
18 | public class Tab {
19 |
20 | private Context context;
21 | private int index;
22 | //是否被选中
23 | private boolean isSelected;
24 |
25 | /**
26 | * 文本信息
27 | */
28 | private String text;
29 | private int textColor;
30 | private int selectedTextColor;
31 | private int textSize;
32 | private int drawablePadding;
33 |
34 |
35 | /**
36 | * icon信息
37 | */
38 | private int iconImage;
39 | private int selectedIconImage;
40 | private int iconHeight;
41 | private int iconWidth;
42 |
43 | /**
44 | * Tab布局信息
45 | */
46 | private RelativeLayout childView;
47 | private LinearLayout rootView;
48 | private ImageView iconImageView;
49 | private TextView textTextView;
50 | private boolean hasMsg;
51 |
52 | /**
53 | * tab选中监听
54 | */
55 | private OnTabSelectedListener onTabSelectedListener;
56 |
57 | public Tab(Context context, String text, int textSize, int textColor, int selectedTextColor, int drawablePadding, int iconWidth, int iconHeight, int iconImage, int selectedIconImage, int index, boolean hasMsg) {
58 | this.context = context;
59 | this.text = text;
60 | this.textSize = textSize;
61 | this.textColor = textColor;
62 | this.selectedTextColor = selectedTextColor;
63 | this.drawablePadding=drawablePadding;
64 |
65 | this.iconImage = iconImage;
66 | this.selectedIconImage = selectedIconImage;
67 | this.index = index;
68 | this.iconHeight=iconHeight;
69 | this.iconWidth=iconWidth;
70 | this.hasMsg=hasMsg;
71 |
72 | init();
73 | }
74 |
75 | private void init() {
76 | initView();
77 |
78 | rootView.setOnClickListener(new View.OnClickListener() {
79 | @Override
80 | public void onClick(View v) {
81 | tabSelected();
82 | }
83 | });
84 | }
85 |
86 | private void initView() {
87 | rootView = new LinearLayout(context);
88 | childView=new RelativeLayout(context);
89 | LinearLayout.LayoutParams rootViewLp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
90 | rootViewLp.weight = 1;
91 | rootView.setOrientation(LinearLayout.VERTICAL);
92 | rootView.setPadding(0,20,0,20);
93 | rootView.setLayoutParams(rootViewLp);
94 | textTextView = new TextView(context);
95 | iconImageView = new ImageView(context);
96 |
97 | /**
98 | * icon view
99 | */
100 | iconImageView.setImageResource(iconImage);
101 | RelativeLayout.LayoutParams iconParam=new RelativeLayout.LayoutParams(iconWidth==0? ViewGroup.LayoutParams.WRAP_CONTENT:iconWidth,iconHeight==0? ViewGroup.LayoutParams.WRAP_CONTENT:iconHeight);
102 | iconParam.addRule(RelativeLayout.CENTER_HORIZONTAL);
103 | iconImageView.setLayoutParams(iconParam);
104 | iconImageView.setId(index+1);
105 | childView.addView(iconImageView);
106 |
107 | /**
108 | * text view
109 | */
110 | textTextView.setText(text);
111 | textTextView.setTextColor(textColor);
112 | textTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX,textSize);
113 | textTextView.setPadding(0,drawablePadding,0,0);
114 | RelativeLayout.LayoutParams txParam=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
115 | txParam.addRule(RelativeLayout.BELOW,childView.getChildAt(0).getId());
116 | txParam.addRule(RelativeLayout.CENTER_HORIZONTAL);
117 | textTextView.setLayoutParams(txParam);
118 | childView.addView(textTextView);
119 |
120 |
121 | if(hasMsg){
122 | ImageView circleView=new ImageView(context);
123 | RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(30,30);
124 | param.addRule(RelativeLayout.RIGHT_OF,iconImageView.getId());
125 | circleView.setBackgroundResource(R.drawable.common_red_round);
126 | circleView.setLayoutParams(param);
127 | childView.addView(circleView);
128 | }
129 | RelativeLayout.LayoutParams childParam=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
130 | childView.setLayoutParams(childParam);
131 | rootView.addView(childView);
132 |
133 | }
134 |
135 | /**
136 | * 选中Tab
137 | */
138 | private void tabSelected() {
139 | if (onTabSelectedListener != null) onTabSelectedListener.onTabSelected(this);
140 | }
141 |
142 | /**
143 | * 得到rootView
144 | */
145 | public LinearLayout getRootView() {
146 | return rootView;
147 | }
148 |
149 | public int getIndex() {
150 | return index;
151 | }
152 |
153 | public String getText() {
154 | return text;
155 | }
156 |
157 | public void setTabIsSelected(boolean isSelected) {
158 | if (this.isSelected == isSelected) return;
159 |
160 | iconImageView.setImageResource(isSelected ? selectedIconImage : iconImage);
161 | textTextView.setTextColor(isSelected ? selectedTextColor : textColor);
162 | this.isSelected = isSelected;
163 | }
164 |
165 | public void setOnTabSelectedListener(OnTabSelectedListener onTabSelectedListener) {
166 | this.onTabSelectedListener = onTabSelectedListener;
167 | }
168 |
169 | }
170 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chenxi/tabview/widget/TabContainerView.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview.widget;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.content.res.TypedArray;
6 | import android.graphics.Color;
7 | import android.os.Build;
8 | import android.support.v4.view.ViewPager;
9 | import android.util.AttributeSet;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.RelativeLayout;
13 |
14 | import com.chenxi.tabview.R;
15 | import com.chenxi.tabview.adapter.BaseAdapter;
16 | import com.chenxi.tabview.adapter.TabViewPagerAdapter;
17 | import com.chenxi.tabview.listener.OnTabSelectedListener;
18 | import com.chenxi.tabview.tools.DisplayUtil;
19 |
20 | /**
21 | * Created by chengxi on 17/4/26.
22 | */
23 | public class TabContainerView extends RelativeLayout {
24 |
25 |
26 | /**
27 | * 底部TabLayout
28 | */
29 | private TabHost tabHost;
30 | /**
31 | * 中间ViewPager
32 | */
33 | private ViewPager contentViewPager;
34 |
35 | /**
36 | * 文本属性
37 | */
38 | private int textSize;
39 | private int textColor;
40 | private int selectedTextColor;
41 | private int drawablePadding;
42 | /**
43 | * 图标属性
44 | */
45 | private int iconHeight;
46 | private int iconWidth;
47 |
48 | /**
49 | * 分割线
50 | */
51 | private int divideLineColor;
52 | private int divideLineHeight;
53 |
54 | private OnTabSelectedListener onTabSelectedListener;
55 |
56 | public TabContainerView(Context context) {
57 | super(context);
58 | }
59 |
60 | public TabContainerView(Context context, AttributeSet attrs) {
61 | super(context, attrs);
62 | init(context, attrs);
63 | }
64 |
65 | public TabContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
66 | super(context, attrs, defStyleAttr);
67 | init(context, attrs);
68 | }
69 |
70 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
71 | public TabContainerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
72 | super(context, attrs, defStyleAttr, defStyleRes);
73 | init(context, attrs);
74 | }
75 |
76 | private void init(Context context, AttributeSet attrs) {
77 | initStyle(context, attrs);
78 | initTabHost(context);
79 | initDivideLine(context);
80 | initViewPager(context);
81 |
82 | tabHost.setContentViewPager(contentViewPager);
83 | }
84 |
85 | private void initStyle(Context context, AttributeSet attrs) {
86 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TabContainerViewStyle);
87 | textColor = typedArray.getColor(R.styleable.TabContainerViewStyle_tabTextColor, Color.BLACK);
88 | selectedTextColor = typedArray.getColor(R.styleable.TabContainerViewStyle_selectedTextColor, Color.RED);
89 | textSize = typedArray.getDimensionPixelSize(R.styleable.TabContainerViewStyle_tabTextSize, DisplayUtil.dip2px(context,14));
90 | drawablePadding =typedArray.getDimensionPixelSize(R.styleable.TabContainerViewStyle_drawablePadding,DisplayUtil.dip2px(context,4));
91 | iconHeight = typedArray.getDimensionPixelSize(R.styleable.TabContainerViewStyle_iconHeight,0);
92 | iconWidth = typedArray.getDimensionPixelSize(R.styleable.TabContainerViewStyle_iconWidth,0);
93 | divideLineColor = typedArray.getColor(R.styleable.TabContainerViewStyle_divideLineColor, Color.BLACK);
94 | divideLineHeight = typedArray.getDimensionPixelSize(R.styleable.TabContainerViewStyle_divideLineHeight,DisplayUtil.dip2px(context,1));
95 |
96 | typedArray.recycle();
97 | }
98 |
99 |
100 | private void initTabHost(Context context) {
101 | tabHost = new TabHost(context);
102 | addView(tabHost.getRootView());
103 | }
104 |
105 | private void initDivideLine(Context context) {
106 | View divideLine = new View(context);
107 | divideLine.setId(R.id.divide_tab);
108 | divideLine.setBackgroundColor(divideLineColor);
109 | LayoutParams lineLp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, divideLineHeight);
110 | lineLp.addRule(RelativeLayout.ABOVE, R.id.linearlayout_tab);
111 | divideLine.setLayoutParams(lineLp);
112 | addView(divideLine);
113 | }
114 |
115 | private void initViewPager(Context context) {
116 | contentViewPager = new ViewPager(context);
117 | LayoutParams contentVpLp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
118 | contentVpLp.addRule(RelativeLayout.ABOVE, R.id.divide_tab);
119 | contentViewPager.setLayoutParams(contentVpLp);
120 | contentViewPager.setId(R.id.viewpager_tab);
121 |
122 | contentViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
123 | @Override
124 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
125 | }
126 |
127 | @Override
128 | public void onPageSelected(int position) {
129 | tabHost.onChangeTabHostStatus(position);
130 | Tab selectedTab = tabHost.getTabForIndex(position);
131 | if (onTabSelectedListener != null && selectedTab != null) onTabSelectedListener.onTabSelected(selectedTab);
132 | }
133 |
134 | @Override
135 | public void onPageScrollStateChanged(int state) {
136 | }
137 | });
138 |
139 | addView(contentViewPager);
140 | }
141 |
142 | public void setAdapter(BaseAdapter baseAdapter) {
143 | setAdapter(baseAdapter, 0);
144 | }
145 |
146 | public void setAdapter(BaseAdapter baseAdapter, int index) {
147 | if (baseAdapter == null) return;
148 | tabHost.addTabs(baseAdapter, textSize, textColor, selectedTextColor,drawablePadding,iconWidth,iconHeight);
149 |
150 | contentViewPager.setAdapter(new TabViewPagerAdapter(baseAdapter.getFragmentManager(), baseAdapter.getFragmentArray()));
151 |
152 | setCurrentItem(index);
153 | }
154 |
155 | public void setCurrentItem(int index) {
156 | tabHost.onChangeTabHostStatus(index);
157 | }
158 |
159 | public void setOnTabSelectedListener(OnTabSelectedListener onTabSelectedListener) {
160 | this.onTabSelectedListener = onTabSelectedListener;
161 | }
162 |
163 |
164 | }
165 |
--------------------------------------------------------------------------------
/app/src/main/java/com/chenxi/tabview/widget/TabHost.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview.widget;
2 |
3 | import android.content.Context;
4 | import android.support.v4.view.ViewPager;
5 | import android.view.ViewGroup;
6 | import android.widget.LinearLayout;
7 | import android.widget.RelativeLayout;
8 |
9 | import com.chenxi.tabview.R;
10 | import com.chenxi.tabview.adapter.BaseAdapter;
11 | import com.chenxi.tabview.listener.OnTabSelectedListener;
12 |
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | /**
17 | * Created by chengxi on 17/4/26.
18 | */
19 | public class TabHost {
20 |
21 |
22 | private Context context;
23 | /**
24 | * 布局View
25 | */
26 | private LinearLayout rootView;
27 | //tab集合
28 | private List tabList = new ArrayList<>();
29 | private ViewPager contentViewPager;
30 |
31 |
32 | public TabHost(Context context) {
33 | this.context = context;
34 | initView();
35 | }
36 |
37 | private void initView() {
38 | rootView = new LinearLayout(context);
39 | rootView.setOrientation(LinearLayout.HORIZONTAL);
40 | rootView.setId(R.id.linearlayout_tab);
41 |
42 | RelativeLayout.LayoutParams rootViewLp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
43 | rootViewLp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
44 | rootView.setLayoutParams(rootViewLp);
45 | }
46 |
47 | private void addTab(Tab tab) {
48 | if (tab == null) return;
49 | tabList.add(tab);
50 |
51 | LinearLayout tabRootView = tab.getRootView();
52 | rootView.addView(tabRootView);
53 |
54 | addTabChangeListener(tab);
55 | }
56 |
57 | public void addTabs(BaseAdapter baseAdapter, int textSize, int textColor, int selectedTextColor, int drawablePadding, int iconWidth, int iconHeight) {
58 | int count = baseAdapter.getCount();
59 | int hasMsgIndex=baseAdapter.hasMsgIndex();
60 | String[] textArray = baseAdapter.getTextArray();
61 | int[] iconImageArray = baseAdapter.getIconImageArray();
62 | int[] selectedIconImageArray = baseAdapter.getSelectedIconImageArray();
63 |
64 | if (count == 0 || textArray == null || iconImageArray == null || selectedIconImageArray == null) return;
65 | if (textArray.length != count || iconImageArray.length != count || selectedIconImageArray.length != count) return;
66 | boolean hasMsg=false;
67 | for (int i = 0; i < count; i++) {
68 | if((i+1)==hasMsgIndex){
69 | hasMsg=true;
70 | }
71 | Tab tab = new Tab(context, textArray[i], textSize, textColor, selectedTextColor,drawablePadding,iconWidth,iconHeight, iconImageArray[i], selectedIconImageArray[i], i,hasMsg);
72 | addTab(tab);
73 | }
74 | }
75 |
76 | public void setContentViewPager(ViewPager contentViewPager) {
77 | this.contentViewPager = contentViewPager;
78 | }
79 |
80 | public LinearLayout getRootView() {
81 | return rootView;
82 | }
83 |
84 | private void addTabChangeListener(Tab tab) {
85 | tab.setOnTabSelectedListener(new OnTabSelectedListener() {
86 | @Override
87 | public void onTabSelected(Tab tab) {
88 | contentViewPager.setCurrentItem(tab.getIndex(), false);
89 | }
90 | });
91 | }
92 |
93 | /**
94 | * 改变tabHost状态
95 | */
96 | public void onChangeTabHostStatus(int index) {
97 | for (int i = 0, size = tabList.size(); i < size; i++) {
98 | Tab tab = tabList.get(i);
99 | tab.setTabIsSelected(index == i ? true : false);
100 | }
101 | }
102 |
103 | public Tab getTabForIndex(int index) {
104 | if (tabList.size() <= index) {
105 | return null;
106 | }
107 | return tabList.get(index);
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/common_red_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main_container.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_tab_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_tab_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_tab_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_tab_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_tab_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/elep_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xicode-ai/TabView/f8d80d4a4eb9f5af7d1523efe19d27f431c5d930/app/src/main/res/mipmap-xhdpi/elep_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/elep_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xicode-ai/TabView/f8d80d4a4eb9f5af7d1523efe19d27f431c5d930/app/src/main/res/mipmap-xxhdpi/elep_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/new_find_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xicode-ai/TabView/f8d80d4a4eb9f5af7d1523efe19d27f431c5d930/app/src/main/res/mipmap-xxhdpi/new_find_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/new_find_icon_grey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xicode-ai/TabView/f8d80d4a4eb9f5af7d1523efe19d27f431c5d930/app/src/main/res/mipmap-xxhdpi/new_find_icon_grey.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/new_finial_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xicode-ai/TabView/f8d80d4a4eb9f5af7d1523efe19d27f431c5d930/app/src/main/res/mipmap-xxhdpi/new_finial_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/new_fininal_icon_grey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xicode-ai/TabView/f8d80d4a4eb9f5af7d1523efe19d27f431c5d930/app/src/main/res/mipmap-xxhdpi/new_fininal_icon_grey.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/new_life_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xicode-ai/TabView/f8d80d4a4eb9f5af7d1523efe19d27f431c5d930/app/src/main/res/mipmap-xxhdpi/new_life_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/new_life_icon_grey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xicode-ai/TabView/f8d80d4a4eb9f5af7d1523efe19d27f431c5d930/app/src/main/res/mipmap-xxhdpi/new_life_icon_grey.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/new_myhome_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xicode-ai/TabView/f8d80d4a4eb9f5af7d1523efe19d27f431c5d930/app/src/main/res/mipmap-xxhdpi/new_myhome_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/new_myhome_icon_grey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xicode-ai/TabView/f8d80d4a4eb9f5af7d1523efe19d27f431c5d930/app/src/main/res/mipmap-xxhdpi/new_myhome_icon_grey.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/new_shoppingcar_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xicode-ai/TabView/f8d80d4a4eb9f5af7d1523efe19d27f431c5d930/app/src/main/res/mipmap-xxhdpi/new_shoppingcar_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/new_shoppingcar_icon_grey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xicode-ai/TabView/f8d80d4a4eb9f5af7d1523efe19d27f431c5d930/app/src/main/res/mipmap-xxhdpi/new_shoppingcar_icon_grey.png
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #EB0000
4 | #b5b5b5
5 | #dcdcdc
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | TabView
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/test/java/com/chenxi/tabview/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.chenxi.tabview;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------