aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurimas Liutikas <aurimas@google.com>2016-10-26 00:14:26 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2016-10-26 00:14:27 +0000
commitc4037564222e361cb92bbc05a062f8da91be5f5f (patch)
tree2e5ff3d76be834454f5dad13e9da974962b4e61a
parent2e2060d9e02a4b78ef885d9c68ba7b8c2304b800 (diff)
parent578015fc3e5ddc0fdb95db7ad0d00822c54be6df (diff)
downloadsupport-nougat-mr1-dev.tar.gz
Merge changes Id091acf5,Ie27b07ae,I701a2582,I32122d77 into nyc-mr1-devnougat-mr1-dev
* changes: Start using return value of OnNavigationItemSelectedListener. Clean up BottomBar docs Force BottomNavigationView item labels to be singleLine. Clean-up BottomNavigationMenuView#onMeasure and other style fixes.
-rw-r--r--design/res/layout/design_bottom_navigation_item.xml2
-rw-r--r--design/src/android/support/design/internal/BottomNavigationMenuView.java63
-rw-r--r--design/src/android/support/design/widget/BottomNavigationView.java26
-rw-r--r--design/tests/src/android/support/design/widget/BottomNavigationViewTest.java28
-rw-r--r--samples/SupportDesignDemos/res/layout/design_bottom_navigation_view.xml66
-rw-r--r--samples/SupportDesignDemos/res/menu/sample_bottom_menu.xml2
-rw-r--r--samples/SupportDesignDemos/src/com/example/android/support/design/widget/BottomNavigationViewUsage.java23
7 files changed, 155 insertions, 55 deletions
diff --git a/design/res/layout/design_bottom_navigation_item.xml b/design/res/layout/design_bottom_navigation_item.xml
index cc7bb5ffe04..67df838533d 100644
--- a/design/res/layout/design_bottom_navigation_item.xml
+++ b/design/res/layout/design_bottom_navigation_item.xml
@@ -34,6 +34,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/design_bottom_navigation_text_size"
+ android:singleLine="true"
android:duplicateParentState="true" />
<TextView
android:id="@+id/largeLabel"
@@ -41,6 +42,7 @@
android:layout_height="wrap_content"
android:visibility="invisible"
android:textSize="@dimen/design_bottom_navigation_active_text_size"
+ android:singleLine="true"
android:duplicateParentState="true" />
</android.support.design.internal.BaselineLayout>
</merge> \ No newline at end of file
diff --git a/design/src/android/support/design/internal/BottomNavigationMenuView.java b/design/src/android/support/design/internal/BottomNavigationMenuView.java
index 158dda7b0be..096bdd83aa0 100644
--- a/design/src/android/support/design/internal/BottomNavigationMenuView.java
+++ b/design/src/android/support/design/internal/BottomNavigationMenuView.java
@@ -16,6 +16,8 @@
package android.support.design.internal;
+import static android.support.annotation.RestrictTo.Scope.GROUP_ID;
+
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
@@ -32,8 +34,6 @@ import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
-import static android.support.annotation.RestrictTo.Scope.GROUP_ID;
-
/**
* @hide For internal use only.
*/
@@ -55,6 +55,7 @@ public class BottomNavigationMenuView extends ViewGroup implements MenuView {
private ColorStateList mItemIconTint;
private ColorStateList mItemTextColor;
private int mItemBackgroundRes;
+ private int[] mTempChildWidths;
private BottomNavigationPresenter mPresenter;
private MenuBuilder mMenu;
@@ -85,10 +86,12 @@ public class BottomNavigationMenuView extends ViewGroup implements MenuView {
public void onClick(View v) {
final BottomNavigationItemView itemView = (BottomNavigationItemView) v;
final int itemPosition = itemView.getItemPosition();
- activateNewButton(itemPosition);
- mMenu.performItemAction(itemView.getItemData(), mPresenter, 0);
+ if (!mMenu.performItemAction(itemView.getItemData(), mPresenter, 0)) {
+ activateNewButton(itemPosition);
+ }
}
};
+ mTempChildWidths = new int[BottomNavigationMenu.MAX_ITEM_COUNT];
}
@Override
@@ -105,10 +108,8 @@ public class BottomNavigationMenuView extends ViewGroup implements MenuView {
final int width = MeasureSpec.getSize(widthMeasureSpec);
final int count = getChildCount();
- final int childState = 0;
final int heightSpec = MeasureSpec.makeMeasureSpec(mItemHeight, MeasureSpec.EXACTLY);
- final int[] childWidths = new int[count];
if (mShiftingMode) {
final int inactiveCount = count - 1;
final int activeMaxAvailable = width - inactiveCount * mInactiveItemMinWidth;
@@ -117,9 +118,9 @@ public class BottomNavigationMenuView extends ViewGroup implements MenuView {
final int inactiveWidth = Math.min(inactiveMaxAvailable, mInactiveItemMaxWidth);
int extra = width - activeWidth - inactiveWidth * inactiveCount;
for (int i = 0; i < count; i++) {
- childWidths[i] = (i == mActiveButton) ? activeWidth : inactiveWidth;
+ mTempChildWidths[i] = (i == mActiveButton) ? activeWidth : inactiveWidth;
if (extra > 0) {
- childWidths[i]++;
+ mTempChildWidths[i]++;
extra--;
}
}
@@ -128,9 +129,9 @@ public class BottomNavigationMenuView extends ViewGroup implements MenuView {
final int childWidth = Math.min(maxAvailable, mActiveItemMaxWidth);
int extra = width - childWidth * count;
for (int i = 0; i < count; i++) {
- childWidths[i] = childWidth;
+ mTempChildWidths[i] = childWidth;
if (extra > 0) {
- childWidths[i]++;
+ mTempChildWidths[i]++;
extra--;
}
}
@@ -142,7 +143,7 @@ public class BottomNavigationMenuView extends ViewGroup implements MenuView {
if (child.getVisibility() == GONE) {
continue;
}
- child.measure(MeasureSpec.makeMeasureSpec(childWidths[i], MeasureSpec.EXACTLY),
+ child.measure(MeasureSpec.makeMeasureSpec(mTempChildWidths[i], MeasureSpec.EXACTLY),
heightSpec);
ViewGroup.LayoutParams params = child.getLayoutParams();
params.width = child.getMeasuredWidth();
@@ -150,9 +151,8 @@ public class BottomNavigationMenuView extends ViewGroup implements MenuView {
}
setMeasuredDimension(
ViewCompat.resolveSizeAndState(totalWidth,
- MeasureSpec.makeMeasureSpec(totalWidth, MeasureSpec.EXACTLY), childState),
- ViewCompat.resolveSizeAndState(mItemHeight, heightSpec,
- childState << MEASURED_HEIGHT_STATE_SHIFT));
+ MeasureSpec.makeMeasureSpec(totalWidth, MeasureSpec.EXACTLY), 0),
+ ViewCompat.resolveSizeAndState(mItemHeight, heightSpec, 0));
}
@Override
@@ -180,19 +180,34 @@ public class BottomNavigationMenuView extends ViewGroup implements MenuView {
return 0;
}
- public void setIconTintList(ColorStateList color) {
- mItemIconTint = color;
+ /**
+ * Set the tint which is applied to the menu items' icons.
+ *
+ * @param tint the tint to apply.
+ */
+ public void setIconTintList(ColorStateList tint) {
+ mItemIconTint = tint;
if (mButtons == null) return;
for (BottomNavigationItemView item : mButtons) {
- item.setIconTintList(color);
+ item.setIconTintList(tint);
}
}
+ /**
+ * Returns the tint which is applied to menu items' icons.
+ *
+ * @return The ColorStateList that is used to tint menu items' icons.
+ */
@Nullable
public ColorStateList getIconTintList() {
return mItemIconTint;
}
+ /**
+ * Set the text color to be used on menu items.
+ *
+ * @param color the ColorStateList used for menu items' text.
+ */
public void setItemTextColor(ColorStateList color) {
mItemTextColor = color;
if (mButtons == null) return;
@@ -201,10 +216,19 @@ public class BottomNavigationMenuView extends ViewGroup implements MenuView {
}
}
+ /**
+ * Returns the text color used on menu items.
+ *
+ * @return the ColorStateList used for menu items' text.
+ */
public ColorStateList getItemTextColor() {
return mItemTextColor;
}
+ /**
+ * Sets the resource id to be used for item background.
+ * @param background the resource id of the background.
+ */
public void setItemBackgroundRes(int background) {
mItemBackgroundRes = background;
if (mButtons == null) return;
@@ -213,6 +237,11 @@ public class BottomNavigationMenuView extends ViewGroup implements MenuView {
}
}
+ /**
+ * Returns the background resource of the menu items.
+ *
+ * @return the resource id of the background.
+ */
public int getItemBackgroundRes() {
return mItemBackgroundRes;
}
diff --git a/design/src/android/support/design/widget/BottomNavigationView.java b/design/src/android/support/design/widget/BottomNavigationView.java
index 476889fe829..8a8e0bd052f 100644
--- a/design/src/android/support/design/widget/BottomNavigationView.java
+++ b/design/src/android/support/design/widget/BottomNavigationView.java
@@ -56,14 +56,28 @@ import android.widget.FrameLayout;
* </p>
*
* <pre>
+ * layout resource file:
* &lt;android.support.design.widget.BottomNavigationView
* xmlns:android="http://schemas.android.com/apk/res/android"
* xmlns:design="http://schema.android.com/apk/res/android.support.design"
* android:id="@+id/navigation"
- * android:layout_width="wrap_content"
- * android:layout_height="match_parent"
+ * android:layout_width="match_parent"
+ * android:layout_height="56dp"
* android:layout_gravity="start"
* design:menu="@menu/my_navigation_items" /&gt;
+ *
+ * res/menu/my_navigation_items.xml:
+ * &lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+ * &lt;item android:id="@+id/action_search"
+ * android:title="@string/menu_search"
+ * android:icon="@drawable/ic_search" /&gt;
+ * &lt;item android:id="@+id/action_settings"
+ * android:title="@string/menu_settings"
+ * android:icon="@drawable/ic_add" /&gt;
+ * &lt;item android:id="@+id/action_navigation"
+ * android:title="@string/menu_navigation"
+ * android:icon="@drawable/ic_action_navigation_menu" /&gt;
+ * &lt;/menu&gt;
* </pre>
*/
public class BottomNavigationView extends FrameLayout {
@@ -138,7 +152,7 @@ public class BottomNavigationView extends FrameLayout {
mMenu.setCallback(new MenuBuilder.Callback() {
@Override
public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
- return mListener != null && mListener.onNavigationItemSelected(item);
+ return mListener != null && !mListener.onNavigationItemSelected(item);
}
@Override
@@ -210,7 +224,7 @@ public class BottomNavigationView extends FrameLayout {
}
/**
- * Returns the tint which is applied to menu items' icons.
+ * Returns the text color used on menu items.
*
* @see #setItemTextColor(ColorStateList)
*
@@ -265,7 +279,9 @@ public class BottomNavigationView extends FrameLayout {
*
* @param item The selected item
*
- * @return true to display the item as the selected item
+ * @return true to display the item as the selected item and false if the item should not
+ * be selected. Consider setting non-selectable items as disabled preemptively to
+ * make them appear non-interactive.
*/
boolean onNavigationItemSelected(@NonNull MenuItem item);
}
diff --git a/design/tests/src/android/support/design/widget/BottomNavigationViewTest.java b/design/tests/src/android/support/design/widget/BottomNavigationViewTest.java
index 98851b4c66a..0ddbc6d51d0 100644
--- a/design/tests/src/android/support/design/widget/BottomNavigationViewTest.java
+++ b/design/tests/src/android/support/design/widget/BottomNavigationViewTest.java
@@ -27,11 +27,15 @@ import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.core.AllOf.allOf;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
import android.content.res.Resources;
import android.support.annotation.ColorInt;
@@ -95,22 +99,38 @@ public class BottomNavigationViewTest
mock(BottomNavigationView.OnNavigationItemSelectedListener.class);
mBottomNavigation.setOnNavigationItemSelectedListener(mockedListener);
- // Click one of our items
+ // Make the listener return true to allow selecting the item.
+ when(mockedListener.onNavigationItemSelected(any(MenuItem.class))).thenReturn(true);
onView(allOf(withText(mMenuStringContent.get(R.id.destination_profile)),
isDescendantOfA(withId(R.id.bottom_navigation)), isDisplayed())).perform(click());
- // And that our listener has been notified of the click
+ // Verify our listener has been notified of the click
verify(mockedListener, times(1)).onNavigationItemSelected(
mBottomNavigation.getMenu().findItem(R.id.destination_profile));
+ // Verify the item is now selected
+ assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_profile).isChecked());
+
+ // Make the listener return false to disallow selecting the item.
+ when(mockedListener.onNavigationItemSelected(any(MenuItem.class))).thenReturn(false);
+ onView(allOf(withText(mMenuStringContent.get(R.id.destination_people)),
+ isDescendantOfA(withId(R.id.bottom_navigation)), isDisplayed())).perform(click());
+ // Verify our listener has been notified of the click
+ verify(mockedListener, times(1)).onNavigationItemSelected(
+ mBottomNavigation.getMenu().findItem(R.id.destination_people));
+ // Verify the previous item is still selected
+ assertFalse(mBottomNavigation.getMenu().findItem(R.id.destination_people).isChecked());
+ assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_profile).isChecked());
// Set null listener to test that the next click is not going to notify the
- // previously set listener
+ // previously set listener and will allow selecting items.
mBottomNavigation.setOnNavigationItemSelectedListener(null);
// Click one of our items
- onView(allOf(withText(mMenuStringContent.get(R.id.destination_people)),
+ onView(allOf(withText(mMenuStringContent.get(R.id.destination_home)),
isDescendantOfA(withId(R.id.bottom_navigation)), isDisplayed())).perform(click());
// And that our previous listener has not been notified of the click
verifyNoMoreInteractions(mockedListener);
+ // Verify the correct item is now selected.
+ assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_home).isChecked());
}
@Test
diff --git a/samples/SupportDesignDemos/res/layout/design_bottom_navigation_view.xml b/samples/SupportDesignDemos/res/layout/design_bottom_navigation_view.xml
index 83e731470fe..c86843009aa 100644
--- a/samples/SupportDesignDemos/res/layout/design_bottom_navigation_view.xml
+++ b/samples/SupportDesignDemos/res/layout/design_bottom_navigation_view.xml
@@ -14,46 +14,56 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<RelativeLayout
+<FrameLayout
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">
- <Button
- android:id="@+id/button_disable"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/bottomnavigation_disable"/>
-
- <Button
- android:id="@+id/button_add"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/bottomnavigation_add"
- android:layout_below="@+id/button_disable"/>
+ <ScrollView android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginBottom="56dp">
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <Button
+ android:id="@+id/button_disable"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/bottomnavigation_disable"/>
+ <Button
+ android:id="@+id/button_add"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/bottomnavigation_add"
+ android:layout_below="@+id/button_disable"/>
- <Button
- android:id="@+id/button_remove"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/bottomnavigation_remove"
- android:layout_below="@+id/button_add"/>
+ <Button
+ android:id="@+id/button_remove"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/bottomnavigation_remove"
+ android:layout_below="@+id/button_add"/>
- <Button
- android:id="@+id/button_tint"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/bottomnavigation_tint"
- android:layout_below="@+id/button_remove"/>
+ <Button
+ android:id="@+id/button_tint"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/bottomnavigation_tint"
+ android:layout_below="@+id/button_remove"/>
+ <TextView
+ android:id="@+id/selected_item"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/button_tint"/>
+ </RelativeLayout>
+ </ScrollView>
<android.support.design.widget.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_gravity="bottom"
android:background="#eee"
- android:layout_alignParentBottom="true"
app:menu="@menu/sample_bottom_menu"/>
-
-</RelativeLayout>
+</FrameLayout>
diff --git a/samples/SupportDesignDemos/res/menu/sample_bottom_menu.xml b/samples/SupportDesignDemos/res/menu/sample_bottom_menu.xml
index 4294f80c2ba..d6d4761e8f0 100644
--- a/samples/SupportDesignDemos/res/menu/sample_bottom_menu.xml
+++ b/samples/SupportDesignDemos/res/menu/sample_bottom_menu.xml
@@ -20,7 +20,7 @@
<item android:id="@+id/action_settings"
android:title="@string/menu_settings"
android:icon="@drawable/ic_add"/>
- <item android:id="@+id/action_navigation"
+ <item android:id="@+id/action_music"
android:title="@string/tab_text"
android:icon="@drawable/ic_action_navigation_menu"/>
</menu> \ No newline at end of file
diff --git a/samples/SupportDesignDemos/src/com/example/android/support/design/widget/BottomNavigationViewUsage.java b/samples/SupportDesignDemos/src/com/example/android/support/design/widget/BottomNavigationViewUsage.java
index 72b50db10de..34422181ea8 100644
--- a/samples/SupportDesignDemos/src/com/example/android/support/design/widget/BottomNavigationViewUsage.java
+++ b/samples/SupportDesignDemos/src/com/example/android/support/design/widget/BottomNavigationViewUsage.java
@@ -18,11 +18,13 @@ package com.example.android.support.design.widget;
import android.content.res.ColorStateList;
import android.os.Bundle;
+import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
+import android.widget.TextView;
import com.example.android.support.design.R;
@@ -74,5 +76,26 @@ public class BottomNavigationViewUsage extends AppCompatActivity {
}
}
});
+ final TextView selectedItem = (TextView) findViewById(R.id.selected_item);
+ bottom.setOnNavigationItemSelectedListener(
+ new BottomNavigationView.OnNavigationItemSelectedListener() {
+ @Override
+ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_search:
+ selectedItem.setText("Entering searching mode");
+ break;
+ case R.id.action_settings:
+ selectedItem.setText("Entering settings!?!");
+ break;
+ case R.id.action_music:
+ selectedItem.setText("Play some music");
+ break;
+ default:
+ selectedItem.setText("Selected " + item.getTitle());
+ }
+ return true;
+ }
+ });
}
}