zqcVrnMb0`6xn!u6+TkI_tA}T;mXu6$D3_j>m|nIOGQoPxh>`vIqa-cYvYZN89o@lJ
zq1Gih_WaT1#9C97KR(FV?g?{Z#=jR~d8=KFU9s`nPvaE7(00T0D
zlqAOdP|o0E)Poe(B&FB|rpPH3DCcEjYPj8$Q?d6~YL>mF>WL$dm*9;chY&{T8
z0Y@jhlI3bBz&>D`yOIZueiTru`t3!wFWynVRA#b@BF+5!I~0GK0;f;CivtPhiivf~Z3Y3MPf
zn_O3jk$&N0DWitHpFYz^k+gBN3GTpJH{pCUmV*xw<-_P#?}Y@jTMFeKa>o*P7Ruq8ZZ6&7s77FgAmOc${IL4=?7&`jdQXqFE_u$GOiANi(_Z~
zd$hz{&u-9F?Ha
zSdswkwRI~b*J&M{Cx3meZC?8ZXT$?A*<<;Vu
z8KLyCbSAf3vUBy6uu*+&c$m2A{qi|Hv4;qOi#x`eXK!2l`4aQ6Pusv0hH3ZOVBvuL
zlM-QzywS|SJ&x-xPfVw2io%{rAe{m!yF{8>!?5B6E-^jN|X|H
zCqh()S53q&g{0dJyy)66+8kc<8FIL~fd;--`&6G^v;qYn$X;LcW&rF!$Hk2W9DL*g
z;U}HLY!T-*v8Kil#IB=SBw#y|np?)l<{k@$mf&^LuNacW%gli-3Js=w(wCLc~|5541Ik6yXhuQs>>^>aHF~X$n?R=Sz_~*0WLiN&624`xgxGj4l&bPNIgw!vXxo
z=c$1S-P9N_NJC7Mk8{e!`lyy+yI;=~wY9@poTB8&N61NvVvchkTXNtd73|YUUtc}K
z^Bm(!AGd2F!l&XKm1Nino4|D9#qc)F3Q}R=vpcsWNQm=!+JZjxhqDuVG2&(HAn_~r
zYeG$zX)EH0Da2|A+U9-3{bzYFLZ`qdg39#Kxxn>-u+i(;m_=rx8e4nD=g*mnZVy7H
za<$&wtRyUwwb|^%=QsJ)m{9Mn@OeMhm$7y;!qTYCz*d>}LT{>bh5VJ%F`m9zcDc(H
z#bR84({^Hc_2{|C8q&(|KrUg-@07TeJKV}KZ^hQ`dpNq-&`wO~Iw=V4DR<2N&}5~72IhvXnFg`gN)za);VJA193ojNh*kh=X&!^rI#4K_UN
zqzF9ev`q}Zwi7)i+YfwC-ukN)h{~^#GG|9pDyVANJ?2>}kM@j_tvfL3npc+)CVNKZ
z_qjC0@DD@Eq4r9W{>q};;7&6pKQ5Jlfx9NQu(3t?Pw%TTEI&IPcf#AoHEQhL)2@!m
z`OvqjB;vhD0eqT`4K!+$#C&CC?aJy6m0Nf-zM}R>Efp}0rptGwS*;%zuFS;CB-$ll
zXoCK49poDA>bjxog#|VJYz!WNa!R5gd|1X
z4M)LmHq-iz`M|*6meq&Ki)B~SKU%4!-)e7QBdC}W<>@WA^_uU{UaY-`Tq!a2mQ`*^
z?L#~WQSlxPVlOr_!4$?u#yDN;{+*OcHNOuT*$)b;qbSZrLku$bz~G0q<>-5f9IcnG3tM}{|T!8yUJfy`tQxaUsn1r
uGyUiIACuGnU;f`e@VBG*mt_$CXYzmh3y1<5`d
-
+
-
-
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/viewpager/BaseFragment.java b/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/BaseFragment.java
similarity index 94%
rename from app/src/main/java/com/ittianyu/bottomnavigationviewexsample/viewpager/BaseFragment.java
rename to app/src/main/java/com/ittianyu/bottomnavigationviewexsample/BaseFragment.java
index 9ad5827..929835d 100644
--- a/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/viewpager/BaseFragment.java
+++ b/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/BaseFragment.java
@@ -1,4 +1,4 @@
-package com.ittianyu.bottomnavigationviewexsample.viewpager;
+package com.ittianyu.bottomnavigationviewexsample;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
diff --git a/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/MainActivity.java b/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/MainActivity.java
index 19cc2ed..2081333 100644
--- a/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/MainActivity.java
+++ b/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/MainActivity.java
@@ -7,7 +7,9 @@
import android.view.View;
import com.ittianyu.bottomnavigationviewexsample.databinding.ActivityMainBinding;
+import com.ittianyu.bottomnavigationviewexsample.setupwithviewpager.SetupWithViewPagerActivity;
import com.ittianyu.bottomnavigationviewexsample.style.StyleActivity;
+import com.ittianyu.bottomnavigationviewexsample.viewbadger.ViewBadgerActivity;
import com.ittianyu.bottomnavigationviewexsample.viewpager.WithViewPagerActivity;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@@ -25,6 +27,8 @@ protected void onCreate(Bundle savedInstanceState) {
private void init() {
binding.btnStyle.setOnClickListener(this);
binding.btnWithViewPager.setOnClickListener(this);
+ binding.btnSetupWithViewPager.setOnClickListener(this);
+ binding.btnViewBadger.setOnClickListener(this);
}
@@ -37,6 +41,13 @@ public void onClick(View view) {
case R.id.btn_with_view_pager:
startActivity(new Intent(this, WithViewPagerActivity.class));
break;
+ case R.id.btn_setup_with_view_pager:
+ startActivity(new Intent(this, SetupWithViewPagerActivity.class));
+ break;
+ case R.id.btn_view_badger:
+ startActivity(new Intent(this, ViewBadgerActivity.class));
+ break;
+
}
}
}
diff --git a/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/setupwithviewpager/SetupWithViewPagerActivity.java b/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/setupwithviewpager/SetupWithViewPagerActivity.java
new file mode 100644
index 0000000..decf9a2
--- /dev/null
+++ b/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/setupwithviewpager/SetupWithViewPagerActivity.java
@@ -0,0 +1,123 @@
+package com.ittianyu.bottomnavigationviewexsample.setupwithviewpager;
+
+import android.databinding.DataBindingUtil;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.design.widget.BottomNavigationView;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+import android.view.MenuItem;
+
+import com.ittianyu.bottomnavigationviewexsample.BaseFragment;
+import com.ittianyu.bottomnavigationviewexsample.R;
+import com.ittianyu.bottomnavigationviewexsample.databinding.ActivityWithViewPagerBinding;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SetupWithViewPagerActivity extends AppCompatActivity {
+ private static final String TAG = SetupWithViewPagerActivity.class.getSimpleName();
+ private ActivityWithViewPagerBinding bind;
+ private VpAdapter adapter;
+
+ // collections
+ private List fragments;// used for ViewPager adapter
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+// setContentView(R.layout.activity_with_view_pager);
+ bind = DataBindingUtil.setContentView(this, R.layout.activity_with_view_pager);
+
+ initView();
+ initData();
+ initEvent();
+ }
+
+ /**
+ * change BottomNavigationViewEx style
+ */
+ private void initView() {
+ bind.bnve.enableItemShiftingMode(true);
+ bind.bnve.enableAnimation(false);
+ }
+
+ /**
+ * create fragments
+ */
+ private void initData() {
+ fragments = new ArrayList<>(3);
+
+ // create music fragment and add it
+ BaseFragment musicFragment = new BaseFragment();
+ Bundle bundle = new Bundle();
+ bundle.putString("title", getString(R.string.music));
+ musicFragment.setArguments(bundle);
+
+ // create backup fragment and add it
+ BaseFragment backupFragment = new BaseFragment();
+ bundle = new Bundle();
+ bundle.putString("title", getString(R.string.backup));
+ backupFragment.setArguments(bundle);
+
+ // create friends fragment and add it
+ BaseFragment friendsFragment = new BaseFragment();
+ bundle = new Bundle();
+ bundle.putString("title", getString(R.string.friends));
+ friendsFragment.setArguments(bundle);
+
+ // add to fragments for adapter
+ fragments.add(musicFragment);
+ fragments.add(backupFragment);
+ fragments.add(friendsFragment);
+
+ // set adapter
+ adapter = new VpAdapter(getSupportFragmentManager(), fragments);
+ bind.vp.setAdapter(adapter);
+
+ // binding with ViewPager
+ bind.bnve.setupWithViewPager(bind.vp);
+ }
+
+ /**
+ * set listeners
+ */
+ private void initEvent() {
+ // set listener to do something then item selected
+ bind.bnve.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
+ @Override
+ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
+ Log.d(TAG, item.getItemId() + " item was selected-------------------");
+ // you can return false to cancel select
+ return true;
+ }
+ });
+
+ }
+
+ /**
+ * view pager adapter
+ */
+ private static class VpAdapter extends FragmentPagerAdapter {
+ private List data;
+
+ public VpAdapter(FragmentManager fm, List data) {
+ super(fm);
+ this.data = data;
+ }
+
+ @Override
+ public int getCount() {
+ return data.size();
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ return data.get(position);
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/viewbadger/ViewBadgerActivity.java b/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/viewbadger/ViewBadgerActivity.java
new file mode 100644
index 0000000..cb42c5b
--- /dev/null
+++ b/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/viewbadger/ViewBadgerActivity.java
@@ -0,0 +1,90 @@
+package com.ittianyu.bottomnavigationviewexsample.viewbadger;
+
+import android.databinding.DataBindingUtil;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.design.widget.BottomNavigationView;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.view.MenuItem;
+import android.widget.ImageView;
+
+import com.ittianyu.bottomnavigationviewexsample.R;
+import com.ittianyu.bottomnavigationviewexsample.databinding.ActivityViewBadgerBinding;
+import com.readystatesoftware.viewbadger.BadgeView;
+
+public class ViewBadgerActivity extends AppCompatActivity {
+ private ActivityViewBadgerBinding bind;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+// setContentView(R.layout.activity_view_badger);
+ bind = DataBindingUtil.setContentView(this, R.layout.activity_view_badger);
+
+ initView();
+ }
+
+ private void initView() {
+ // disable all animations
+ bind.bnve.enableAnimation(false);
+ bind.bnve.enableShiftingMode(false);
+ bind.bnve.enableItemShiftingMode(false);
+
+ // add a BadgeView at second icon
+ bind.bnve.post(new Runnable() {
+ @Override
+ public void run() {
+ final BadgeView badgeView1 = addBadgeViewAt(1, "1");
+ final BadgeView badgeView3 = addBadgeViewAt(3, "99");
+
+ // hide the red circle when click
+ bind.bnve.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
+ @Override
+ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
+ int position = bind.bnve.getMenuItemPosition(item);
+ switch (position) {
+ case 1:
+ badgeView1.toggle(true);
+ break;
+ case 3:
+ badgeView3.toggle(true);
+ break;
+ }
+ return true;
+ }
+ });
+ }
+ });
+ }
+
+ /**
+ * add a BadgeView on icon at position
+ * @param position
+ * @return
+ */
+ private BadgeView addBadgeViewAt(int position, String text) {
+ // get position
+ ImageView icon = bind.bnve.getIconAt(position);
+ int[] pos = new int[2];
+ icon.getLocationInWindow(pos);
+ // action bar height
+ ActionBar actionBar = getSupportActionBar();
+ int actionBarHeight = 0;
+ if (null != actionBar) {
+ actionBarHeight = actionBar.getHeight();
+ }
+ int x = (int) (pos[0] + icon.getMeasuredWidth() * 0.8f);
+ int y = (int) (pos[1] - actionBarHeight - icon.getMeasuredHeight() * 1.2f);
+
+ // create BadgeView: detail for BadgeView click here
+ // https://github.com/jgilfelt/android-viewbadger
+ BadgeView badge = new BadgeView(ViewBadgerActivity.this, bind.rlRoot);
+ badge.setText(text);
+ badge.setBadgePosition(BadgeView.POSITION_TOP_LEFT);
+ badge.setBadgeMargin(x, y);
+ badge.show();
+
+ return badge;
+ }
+}
diff --git a/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/viewpager/WithViewPagerActivity.java b/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/viewpager/WithViewPagerActivity.java
index d0fa91d..4d8e8c7 100644
--- a/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/viewpager/WithViewPagerActivity.java
+++ b/app/src/main/java/com/ittianyu/bottomnavigationviewexsample/viewpager/WithViewPagerActivity.java
@@ -13,6 +13,7 @@
import android.util.SparseArray;
import android.view.MenuItem;
+import com.ittianyu.bottomnavigationviewexsample.BaseFragment;
import com.ittianyu.bottomnavigationviewexsample.R;
import com.ittianyu.bottomnavigationviewexsample.databinding.ActivityWithViewPagerBinding;
@@ -20,12 +21,12 @@
import java.util.List;
public class WithViewPagerActivity extends AppCompatActivity {
- private static final String TAG = WithViewPagerActivity.class.getCanonicalName();
+ private static final String TAG = WithViewPagerActivity.class.getSimpleName();
private ActivityWithViewPagerBinding bind;
private VpAdapter adapter;
// collections
- private SparseArray fragmentMap;// used for change ViewPager selected item
+ private SparseArray items;// used for change ViewPager selected item
private List fragments;// used for ViewPager adapter
@Override
@@ -52,7 +53,7 @@ private void initView() {
*/
private void initData() {
fragments = new ArrayList<>(3);
- fragmentMap = new SparseArray<>(3);
+ items = new SparseArray<>(3);
// create music fragment and add it
BaseFragment musicFragment = new BaseFragment();
@@ -77,10 +78,10 @@ private void initData() {
fragments.add(backupFragment);
fragments.add(friendsFragment);
- // add to fragmentMap for change ViewPager item
- fragmentMap.put(R.id.menu_music, 0);
- fragmentMap.put(R.id.menu_backup, 1);
- fragmentMap.put(R.id.menu_friends, 2);
+ // add to items for change ViewPager item
+ items.put(R.id.menu_music, 0);
+ items.put(R.id.menu_backup, 1);
+ items.put(R.id.menu_friends, 2);
// set adapter
adapter = new VpAdapter(getSupportFragmentManager(), fragments);
@@ -93,6 +94,8 @@ private void initData() {
private void initEvent() {
// set listener to change the current item of view pager when click bottom nav item
bind.bnve.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
+ private int previousPosition = -1;
+
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
// int id = 0;
@@ -107,11 +110,20 @@ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
// id = 2;
// break;
// }
-// bind.vp.setCurrentItem(id, false);
+// if(previousPosition != id) {
+// bind.vp.setCurrentItem(id, false);
+// previousPosition = id;
+// }
// you can write as above.
// I recommend this method. You can change the item order or counts without update code here.
- bind.vp.setCurrentItem(fragmentMap.get(item.getItemId()));
+ int position = items.get(item.getItemId());
+ if (previousPosition != position) {
+ // only set item when item changed
+ previousPosition = position;
+ Log.i(TAG, "-----bnve-------- previous item:" + bind.bnve.getCurrentItem() + " current item:" + position + " ------------------");
+ bind.vp.setCurrentItem(position);
+ }
return true;
}
});
@@ -125,12 +137,8 @@ public void onPageScrolled(int position, float positionOffset, int positionOffse
@Override
public void onPageSelected(int position) {
- // check whether current item is equal position
- if (bind.bnve.getCurrentItem() != position) {
- // only set item when scroll view pager by hand
- bind.bnve.setCurrentItem(position);
- Log.i(TAG, "setCurrentItem:" + position);
- }
+ Log.i(TAG, "-----ViewPager-------- previous item:" + bind.bnve.getCurrentItem() + " current item:" + position + " ------------------");
+ bind.bnve.setCurrentItem(position);
}
@Override
diff --git a/app/src/main/res/color/item_text_color.xml b/app/src/main/res/color/selector_item_color.xml
similarity index 100%
rename from app/src/main/res/color/item_text_color.xml
rename to app/src/main/res/color/selector_item_color.xml
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index bfd1baa..ef319cd 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -25,6 +25,18 @@
android:layout_height="wrap_content"
android:text="@string/with_view_pager" />
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_style.xml b/app/src/main/res/layout/activity_style.xml
index 7f08c19..643f62f 100644
--- a/app/src/main/res/layout/activity_style.xml
+++ b/app/src/main/res/layout/activity_style.xml
@@ -21,8 +21,8 @@
diff --git a/app/src/main/res/layout/activity_view_badger.xml b/app/src/main/res/layout/activity_view_badger.xml
new file mode 100644
index 0000000..6c39d3c
--- /dev/null
+++ b/app/src/main/res/layout/activity_view_badger.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_with_view_pager.xml b/app/src/main/res/layout/activity_with_view_pager.xml
index ac58a3d..6e00acb 100644
--- a/app/src/main/res/layout/activity_with_view_pager.xml
+++ b/app/src/main/res/layout/activity_with_view_pager.xml
@@ -16,8 +16,8 @@
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
app:itemBackground="@color/colorPrimary"
- app:itemIconTint="@color/item_text_color"
- app:itemTextColor="@color/item_text_color"
+ app:itemIconTint="@color/selector_item_color"
+ app:itemTextColor="@color/selector_item_color"
app:menu="@menu/menu_navigation_with_view_pager" />
BottomNavigationViewEx
不同的样式
配合ViewPager
+ 带数字小红点
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 27c3d58..1cdd970 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,4 +1,4 @@
-
+
BottomNavigationViewEx
Music
Backup
@@ -21,4 +21,6 @@
no shifting mode
no animation
normal
+ setup with view pager
+ view badger
diff --git a/widget/build.gradle b/widget/build.gradle
index c1a2050..96a8ea9 100644
--- a/widget/build.gradle
+++ b/widget/build.gradle
@@ -10,8 +10,8 @@ android {
defaultConfig {
minSdkVersion 11
targetSdkVersion 25
- versionCode 1
- versionName "1.0"
+ versionCode 5
+ versionName "1.1.1"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -33,3 +33,32 @@ dependencies {
compile 'com.android.support:design:25.0.1'
testCompile 'junit:junit:4.12'
}
+
+// 指定编码
+tasks.withType(JavaCompile) {
+ options.encoding = "UTF-8"
+}
+
+// 打包源码
+task sourcesJar(type: Jar) {
+ from android.sourceSets.main.java.srcDirs
+ classifier = 'sources'
+}
+
+task javadoc(type: Javadoc) {
+ failOnError false
+ source = android.sourceSets.main.java.sourceFiles
+ classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
+ classpath += configurations.compile
+}
+
+// 制作文档(Javadoc)
+task javadocJar(type: Jar, dependsOn: javadoc) {
+ classifier = 'javadoc'
+ from javadoc.destinationDir
+}
+
+artifacts {
+ archives sourcesJar
+ archives javadocJar
+}
\ No newline at end of file
diff --git a/widget/src/main/java/com/ittianyu/bottomnavigationviewex/BottomNavigationViewEx.java b/widget/src/main/java/com/ittianyu/bottomnavigationviewex/BottomNavigationViewEx.java
index 35219c9..d74edc9 100644
--- a/widget/src/main/java/com/ittianyu/bottomnavigationviewex/BottomNavigationViewEx.java
+++ b/widget/src/main/java/com/ittianyu/bottomnavigationviewex/BottomNavigationViewEx.java
@@ -2,22 +2,29 @@
import android.content.Context;
import android.graphics.Paint;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.design.internal.BottomNavigationItemView;
import android.support.design.internal.BottomNavigationMenuView;
import android.support.design.widget.BottomNavigationView;
+import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
+import android.util.SparseArray;
import android.util.TypedValue;
import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
+import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
/**
* Created by yu on 2016/11/10.
*/
public class BottomNavigationViewEx extends BottomNavigationView {
+ // used for animation
private int mShiftAmount;
private float mScaleUpFactor;
private float mScaleDownFactor;
@@ -27,6 +34,15 @@ public class BottomNavigationViewEx extends BottomNavigationView {
private boolean visibilityTextSizeRecord;
private boolean visibilityHeightRecord;
private int mItemHeight;
+ // used for animation end
+
+ // used for setupWithViewPager
+ private ViewPager mViewPager;
+ private MyOnNavigationItemSelectedListener mMyOnNavigationItemSelectedListener;
+ private BottomNavigationViewExOnPageChangeListener mPageChangeListener;
+ private BottomNavigationMenuView mMenuView;
+ private BottomNavigationItemView[] mButtons;
+ // used for setupWithViewPager end
public BottomNavigationViewEx(Context context) {
super(context);
@@ -61,9 +77,9 @@ public void setIconVisibility(boolean visibility) {
5. change mItemHeight to only text size in mMenuView
*/
// 1. get mMenuView
- final BottomNavigationMenuView mMenuView = getField(getClass().getSuperclass(), this, "mMenuView", BottomNavigationMenuView.class);
+ final BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. get mButtons
- BottomNavigationItemView[] mButtons = getField(mMenuView.getClass(), mMenuView, "mButtons", BottomNavigationItemView[].class);
+ BottomNavigationItemView[] mButtons = getBottomNavigationItemViews();
// 3. get mIcon in mButtons
for (BottomNavigationItemView button : mButtons) {
ImageView mIcon = getField(button.getClass(), button, "mIcon", ImageView.class);
@@ -106,7 +122,6 @@ public void run() {
mMenuView.updateMenuView();
}
-
/**
* change the visibility of text
*
@@ -127,9 +142,9 @@ public void setTextVisibility(boolean visibility) {
4. change mItemHeight to only icon size in mMenuView
*/
// 1. get mMenuView
- final BottomNavigationMenuView mMenuView = getField(getClass().getSuperclass(), this, "mMenuView", BottomNavigationMenuView.class);
+ BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. get mButtons
- BottomNavigationItemView[] mButtons = getField(mMenuView.getClass(), mMenuView, "mButtons", BottomNavigationItemView[].class);
+ BottomNavigationItemView[] mButtons = getBottomNavigationItemViews();
// 3. change field mShiftingMode value in mButtons
for (BottomNavigationItemView button : mButtons) {
TextView mLargeLabel = getField(button.getClass(), button, "mLargeLabel", TextView.class);
@@ -184,6 +199,12 @@ public void setTextVisibility(boolean visibility) {
mMenuView.updateMenuView();
}
+ /**
+ * get text height by font size
+ *
+ * @param fontSize
+ * @return
+ */
private static int getFontHeight(float fontSize) {
Paint paint = new Paint();
paint.setTextSize(fontSize);
@@ -193,6 +214,7 @@ private static int getFontHeight(float fontSize) {
/**
* enable or disable click item animation(text scale and icon move animation in no item shifting mode)
+ *
* @param enable It means the text won't scale and icon won't move when active it in no item shifting mode if false.
*/
public void enableAnimation(boolean enable) {
@@ -216,9 +238,9 @@ public void enableAnimation(boolean enable) {
*/
// 1. get mMenuView
- BottomNavigationMenuView mMenuView = getField(getClass().getSuperclass(), this, "mMenuView", BottomNavigationMenuView.class);
+ BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. get mButtons
- BottomNavigationItemView[] mButtons = getField(mMenuView.getClass(), mMenuView, "mButtons", BottomNavigationItemView[].class);
+ BottomNavigationItemView[] mButtons = getBottomNavigationItemViews();
// 3. change field mShiftingMode value in mButtons
for (BottomNavigationItemView button : mButtons) {
TextView mLargeLabel = getField(button.getClass(), button, "mLargeLabel", TextView.class);
@@ -269,6 +291,7 @@ public void enableAnimation(boolean enable) {
/**
* enable the shifting mode for navigation
+ *
* @param enable It will has a shift animation if true. Otherwise all items are the same width.
*/
public void enableShiftingMode(boolean enable) {
@@ -280,7 +303,7 @@ public void enableShiftingMode(boolean enable) {
private boolean mShiftingMode = true;
*/
// 1. get mMenuView
- BottomNavigationMenuView mMenuView = getField(getClass().getSuperclass(), this, "mMenuView", BottomNavigationMenuView.class);
+ BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. change field mShiftingMode value in mMenuView
setField(mMenuView.getClass(), mMenuView, "mShiftingMode", enable);
@@ -289,6 +312,7 @@ public void enableShiftingMode(boolean enable) {
/**
* enable the shifting mode for each item
+ *
* @param enable It will has a shift animation for item if true. Otherwise the item text always be shown.
*/
public void enableItemShiftingMode(boolean enable) {
@@ -303,9 +327,9 @@ public void enableItemShiftingMode(boolean enable) {
private boolean mShiftingMode = true;
*/
// 1. get mMenuView
- BottomNavigationMenuView mMenuView = getField(getClass().getSuperclass(), this, "mMenuView", BottomNavigationMenuView.class);
+ BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. get mButtons
- BottomNavigationItemView[] mButtons = getField(mMenuView.getClass(), mMenuView, "mButtons", BottomNavigationItemView[].class);
+ BottomNavigationItemView[] mButtons = getBottomNavigationItemViews();
// 3. change field mShiftingMode value in mButtons
for (BottomNavigationItemView button : mButtons) {
setField(button.getClass(), button, "mShiftingMode", enable);
@@ -315,6 +339,7 @@ public void enableItemShiftingMode(boolean enable) {
/**
* get the current checked item position
+ *
* @return index of item, start from 0.
*/
public int getCurrentItem() {
@@ -329,9 +354,9 @@ public int getCurrentItem() {
*/
// 1. get mMenuView
- BottomNavigationMenuView mMenuView = getField(getClass().getSuperclass(), this, "mMenuView", BottomNavigationMenuView.class);
+// BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. get mButtons
- BottomNavigationItemView[] mButtons = getField(mMenuView.getClass(), mMenuView, "mButtons", BottomNavigationItemView[].class);
+ BottomNavigationItemView[] mButtons = getBottomNavigationItemViews();
// 3. get menu and traverse it to get the checked one
Menu menu = getMenu();
for (int i = 0; i < mButtons.length; i++) {
@@ -342,6 +367,26 @@ public int getCurrentItem() {
return 0;
}
+ /**
+ * get menu item position in menu
+ *
+ * @param item
+ * @return position if success, -1 otherwise
+ */
+ public int getMenuItemPosition(MenuItem item) {
+ // get item id
+ int itemId = item.getItemId();
+ // get meunu
+ Menu menu = getMenu();
+ int size = menu.size();
+ for (int i = 0; i < size; i++) {
+ if (menu.getItem(i).getItemId() == itemId) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
/**
* set the current checked item
*
@@ -365,9 +410,9 @@ public void setCurrentItem(int item) {
3. call mOnClickListener.onClick();
*/
// 1. get mMenuView
- BottomNavigationMenuView mMenuView = getField(getClass().getSuperclass(), this, "mMenuView", BottomNavigationMenuView.class);
+ BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. get mButtons
- BottomNavigationItemView[] mButtons = getField(mMenuView.getClass(), mMenuView, "mButtons", BottomNavigationItemView[].class);
+ BottomNavigationItemView[] mButtons = getBottomNavigationItemViews();
// get mOnClickListener
View.OnClickListener mOnClickListener = getField(mMenuView.getClass(), mMenuView, "mOnClickListener", View.OnClickListener.class);
@@ -377,6 +422,79 @@ public void setCurrentItem(int item) {
}
+ /**
+ * get OnNavigationItemSelectedListener
+ *
+ * @return
+ */
+ public OnNavigationItemSelectedListener getOnNavigationItemSelectedListener() {
+ // private OnNavigationItemSelectedListener mListener;
+ OnNavigationItemSelectedListener mListener = getField(getClass().getSuperclass(), this, "mListener", OnNavigationItemSelectedListener.class);
+ return mListener;
+ }
+
+ @Override
+ public void setOnNavigationItemSelectedListener(@Nullable OnNavigationItemSelectedListener listener) {
+ // if not set up with view pager, the same with father
+ if (null == mMyOnNavigationItemSelectedListener) {
+ super.setOnNavigationItemSelectedListener(listener);
+ return;
+ }
+
+ mMyOnNavigationItemSelectedListener.setOnNavigationItemSelectedListener(listener);
+ }
+
+ /**
+ * get private mMenuView
+ * @return
+ */
+ private BottomNavigationMenuView getBottomNavigationMenuView() {
+ if (null == mMenuView)
+ mMenuView = getField(getClass().getSuperclass(), this, "mMenuView", BottomNavigationMenuView.class);
+ return mMenuView;
+ }
+
+ /**
+ * get private mButtons in mMenuView
+ * @return
+ */
+ public BottomNavigationItemView[] getBottomNavigationItemViews() {
+ if (null != mButtons)
+ return mButtons;
+ /*
+ * 1 private final BottomNavigationMenuView mMenuView;
+ * 2 private BottomNavigationItemView[] mButtons;
+ */
+ BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
+ mButtons = getField(mMenuView.getClass(), mMenuView, "mButtons", BottomNavigationItemView[].class);
+ return mButtons;
+ }
+
+ /**
+ * get private mButton in mMenuView at position
+ * @param position
+ * @return
+ */
+ public BottomNavigationItemView getBottomNavigationItemView(int position) {
+ return getBottomNavigationItemViews()[position];
+ }
+
+ /**
+ * get icon at position
+ * @param position
+ * @return
+ */
+ public ImageView getIconAt(int position) {
+ /*
+ * 1 private final BottomNavigationMenuView mMenuView;
+ * 2 private BottomNavigationItemView[] mButtons;
+ * 3 private ImageView mIcon;
+ */
+ BottomNavigationItemView mButtons = getBottomNavigationItemView(position);
+ ImageView mIcon = getField(BottomNavigationItemView.class, mButtons, "mIcon", ImageView.class);
+ return mIcon;
+ }
+
/**
* get private filed in this specific object
*
@@ -389,7 +507,7 @@ public void setCurrentItem(int item) {
*/
private T getField(Class targetClass, Object instance, String fieldName, Class fieldType) {
try {
- Field field = field = targetClass.getDeclaredField(fieldName);
+ Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
return (T) field.get(instance);
} catch (NoSuchFieldException e) {
@@ -404,13 +522,13 @@ private T getField(Class targetClass, Object instance, String fieldName, Cla
* change the field value
*
* @param targetClass
- * @param instance the filed owner
+ * @param instance the filed owner
* @param fieldName
* @param value
*/
private void setField(Class targetClass, Object instance, String fieldName, Object value) {
try {
- Field field = field = targetClass.getDeclaredField(fieldName);
+ Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(instance, value);
} catch (NoSuchFieldException e) {
@@ -420,4 +538,142 @@ private void setField(Class targetClass, Object instance, String fieldName, Obje
}
}
+ /**
+ * This method will link the given ViewPager and this BottomNavigationViewEx together so that
+ * changes in one are automatically reflected in the other. This includes scroll state changes
+ * and clicks.
+ *
+ * @param viewPager
+ */
+ public void setupWithViewPager(@Nullable final ViewPager viewPager) {
+ setupWithViewPager(viewPager, false);
+ }
+
+ /**
+ * This method will link the given ViewPager and this BottomNavigationViewEx together so that
+ * changes in one are automatically reflected in the other. This includes scroll state changes
+ * and clicks.
+ *
+ * @param viewPager
+ * @param smoothScroll whether ViewPager changed with smooth scroll animation
+ */
+ public void setupWithViewPager(@Nullable final ViewPager viewPager, boolean smoothScroll) {
+ if (mViewPager != null) {
+ // If we've already been setup with a ViewPager, remove us from it
+ if (mPageChangeListener != null) {
+ mViewPager.removeOnPageChangeListener(mPageChangeListener);
+ }
+ }
+
+ if (null == viewPager) {
+ mViewPager = null;
+ super.setOnNavigationItemSelectedListener(null);
+ return;
+ }
+
+ mViewPager = viewPager;
+
+ // Add our custom OnPageChangeListener to the ViewPager
+ if (mPageChangeListener == null) {
+ mPageChangeListener = new BottomNavigationViewExOnPageChangeListener(this);
+ }
+ viewPager.addOnPageChangeListener(mPageChangeListener);
+
+ // Now we'll add a navigation item selected listener to set ViewPager's current item
+ OnNavigationItemSelectedListener listener = getOnNavigationItemSelectedListener();
+ mMyOnNavigationItemSelectedListener = new MyOnNavigationItemSelectedListener(viewPager, this, smoothScroll, listener);
+ super.setOnNavigationItemSelectedListener(mMyOnNavigationItemSelectedListener);
+ }
+
+ /**
+ * A {@link ViewPager.OnPageChangeListener} class which contains the
+ * necessary calls back to the provided {@link BottomNavigationViewEx} so that the tab position is
+ * kept in sync.
+ *
+ *
This class stores the provided BottomNavigationViewEx weakly, meaning that you can use
+ * {@link ViewPager#addOnPageChangeListener(ViewPager.OnPageChangeListener)
+ * addOnPageChangeListener(OnPageChangeListener)} without removing the listener and
+ * not cause a leak.
+ */
+ private static class BottomNavigationViewExOnPageChangeListener implements ViewPager.OnPageChangeListener {
+ private final WeakReference mBnveRef;
+
+ public BottomNavigationViewExOnPageChangeListener(BottomNavigationViewEx bnve) {
+ mBnveRef = new WeakReference<>(bnve);
+ }
+
+ @Override
+ public void onPageScrollStateChanged(final int state) {
+ }
+
+ @Override
+ public void onPageScrolled(final int position, final float positionOffset,
+ final int positionOffsetPixels) {
+ }
+
+ @Override
+ public void onPageSelected(final int position) {
+ final BottomNavigationViewEx bnve = mBnveRef.get();
+ if (null != bnve)
+ bnve.setCurrentItem(position);
+// Log.d("onPageSelected", "--------- position " + position + " ------------");
+ }
+ }
+
+ /**
+ * Decorate OnNavigationItemSelectedListener for setupWithViewPager
+ */
+ private static class MyOnNavigationItemSelectedListener implements OnNavigationItemSelectedListener {
+ private OnNavigationItemSelectedListener listener;
+ private ViewPager viewPager;
+ private boolean smoothScroll;
+ private SparseArray items;// used for change ViewPager selected item
+ private int previousPosition = -1;
+
+
+ MyOnNavigationItemSelectedListener(ViewPager viewPager, BottomNavigationViewEx bnve, boolean smoothScroll, OnNavigationItemSelectedListener listener) {
+ this.viewPager = viewPager;
+ this.listener = listener;
+ this.smoothScroll = smoothScroll;
+
+ // create items
+ Menu menu = bnve.getMenu();
+ int size = menu.size();
+ items = new SparseArray<>(size);
+ for (int i = 0; i < size; i++) {
+ int itemId = menu.getItem(i).getItemId();
+ items.put(itemId, i);
+ }
+ }
+
+ public void setOnNavigationItemSelectedListener(OnNavigationItemSelectedListener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
+ int position = items.get(item.getItemId());
+ // only set item when item changed
+ if (previousPosition == position) {
+ return true;
+ }
+
+ // user listener
+ if (null != listener) {
+ boolean bool = listener.onNavigationItemSelected(item);
+ // if the selected is invalid, no need change the view pager
+ if (!bool)
+ return false;
+ }
+ // update previous position
+ previousPosition = position;
+
+ // change view pager
+ viewPager.setCurrentItem(items.get(item.getItemId()), smoothScroll);
+
+ return true;
+ }
+
+ }
+
}