1+ /*
2+ * Copyright 2014 Google Inc. All rights reserved.
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+ package com .nativescript .material .core ;
18+
19+ import android .content .Context ;
20+ import android .graphics .Typeface ;
21+ import android .graphics .Color ;
22+ import android .graphics .drawable .Drawable ;
23+ import android .text .TextUtils ;
24+ import android .util .AttributeSet ;
25+ import android .util .SparseArray ;
26+ import android .util .TypedValue ;
27+ import android .view .Gravity ;
28+ import android .view .View ;
29+ import android .view .ViewGroup ;
30+ import android .widget .ImageView ;
31+ import android .widget .ImageView .ScaleType ;
32+ import android .widget .LinearLayout ;
33+ import android .widget .TextView ;
34+
35+ public class BottomNavigationBar extends LinearLayout {
36+ /**
37+ * Allows complete control over the colors drawn in the tab layout. Set with
38+ * {@link #setCustomTabColorizer(TabColorizer)}.
39+ */
40+ public interface TabColorizer {
41+
42+ /**
43+ * @return return the color of the indicator used when {@code position}
44+ * is selected.
45+ */
46+ int getIndicatorColor (int position );
47+
48+ }
49+
50+ private static final int BOTTOM_NAV_HEIGHT = 56 ;
51+ private static final int ITEM_TEXT_SIZE_SP = 12 ;
52+ private static final int ITEM_TEXT_MAX_WIDTH = 144 ;
53+
54+ private TabItemSpec [] mTabItems ;
55+ private SparseArray <String > mContentDescriptions = new SparseArray <String >();
56+
57+ private final TabStrip mTabStrip ;
58+ private int mMaxImageHeight ;
59+
60+ public BottomNavigationBar (Context context ) {
61+ this (context , null );
62+ }
63+
64+ public BottomNavigationBar (Context context , AttributeSet attrs ) {
65+ this (context , attrs , 0 );
66+ }
67+
68+ public BottomNavigationBar (Context context , AttributeSet attrs , int defStyle ) {
69+ super (context , attrs , defStyle );
70+
71+ mTabStrip = new TabStrip (context );
72+ mTabStrip .setSelectedIndicatorColors (0x00FFFFFF );
73+ int bottomNavHeight = (int ) (BOTTOM_NAV_HEIGHT * getResources ().getDisplayMetrics ().density );
74+ addView (mTabStrip , LayoutParams .MATCH_PARENT , bottomNavHeight );
75+ }
76+
77+ /**
78+ * Set the custom {@link TabColorizer} to be used.
79+ *
80+ * If you only require simple customisation then you can use
81+ */
82+ public void setCustomTabColorizer (TabColorizer tabColorizer ) {
83+ // mTabStrip.setCustomTabColorizer(tabColorizer);
84+ }
85+
86+ public void setTabTextColor (int color ){
87+ mTabStrip .setTabTextColor (color );
88+ }
89+
90+ public int getTabTextColor (){
91+ return mTabStrip .getTabTextColor ();
92+ }
93+
94+ public void setSelectedTabTextColor (int color ){
95+ mTabStrip .setSelectedTabTextColor (color );
96+ }
97+
98+ public int getSelectedTabTextColor (){
99+ return mTabStrip .getSelectedTabTextColor ();
100+ }
101+
102+ public void setTabTextFontSize (float fontSize ){
103+ mTabStrip .setTabTextFontSize (fontSize );
104+ }
105+
106+ public float getTabTextFontSize (){
107+ return mTabStrip .getTabTextFontSize ();
108+ }
109+
110+ public void setItems (TabItemSpec [] items ) {
111+ mTabStrip .removeAllViews ();
112+ mTabItems = items ;
113+ setImageHeights ();
114+ populateTabStrip ();
115+ }
116+
117+ /**
118+ * Updates the UI of an item at specified index
119+ */
120+ public void updateItemAt (int position , TabItemSpec tabItem ) {
121+ LinearLayout ll = (LinearLayout )mTabStrip .getChildAt (position );
122+ ImageView imgView = (ImageView )ll .getChildAt (0 );
123+ TextView textView = (TextView )ll .getChildAt (1 );
124+ this .setupItem (ll , textView , imgView , tabItem );
125+ }
126+
127+ /**
128+ * Gets the TextView for tab item at index
129+ */
130+ public TextView getTextViewForItemAt (int index ){
131+ LinearLayout ll = this .getViewForItemAt (index );
132+ return (ll != null ) ? (TextView )ll .getChildAt (1 ) : null ;
133+ }
134+
135+ /**
136+ * Gets the LinearLayout container for tab item at index
137+ */
138+ public LinearLayout getViewForItemAt (int index ){
139+ LinearLayout result = null ;
140+
141+ if (this .mTabStrip .getChildCount () > index ){
142+ result = (LinearLayout )this .mTabStrip .getChildAt (index );
143+ }
144+
145+ return result ;
146+ }
147+
148+ /**
149+ * Gets the number of realized tabs.
150+ */
151+ public int getItemCount (){
152+ return this .mTabStrip .getChildCount ();
153+ }
154+
155+ /**
156+ * Create a default view to be used for tabs.
157+ */
158+ protected View createDefaultTabView (Context context , TabItemSpec tabItem ) {
159+ float density = getResources ().getDisplayMetrics ().density ;
160+
161+ LinearLayout tabItemLayout = new LinearLayout (context );
162+ tabItemLayout .setLayoutParams (new LinearLayout .LayoutParams (ViewGroup .LayoutParams .WRAP_CONTENT , ViewGroup .LayoutParams .MATCH_PARENT ));
163+ tabItemLayout .setGravity (Gravity .CENTER );
164+ tabItemLayout .setOrientation (LinearLayout .VERTICAL );
165+ TypedValue backgroundOutValue = new TypedValue ();
166+ getContext ().getTheme ().resolveAttribute (android .R .attr .selectableItemBackground , backgroundOutValue , true );
167+ tabItemLayout .setBackgroundResource (backgroundOutValue .resourceId );
168+
169+ ImageView iconImageView = new ImageView (context );
170+ iconImageView .setScaleType (ScaleType .FIT_CENTER );
171+ int iconImageHeight = this .mMaxImageHeight > 0 ? this .mMaxImageHeight : ViewGroup .LayoutParams .WRAP_CONTENT ;
172+ int iconImageWidth = ViewGroup .LayoutParams .WRAP_CONTENT ;
173+ LinearLayout .LayoutParams iconImageLayoutParams = new LinearLayout .LayoutParams (iconImageWidth , iconImageHeight );
174+ iconImageLayoutParams .gravity = Gravity .CENTER ;
175+ iconImageView .setLayoutParams (iconImageLayoutParams );
176+
177+ TextView titleTextView = new TextView (context );
178+ titleTextView .setGravity (Gravity .CENTER );
179+ titleTextView .setMaxWidth ((int ) (ITEM_TEXT_MAX_WIDTH * density ));
180+ titleTextView .setTextSize (TypedValue .COMPLEX_UNIT_SP , ITEM_TEXT_SIZE_SP );
181+ titleTextView .setEllipsize (TextUtils .TruncateAt .END );
182+ titleTextView .setMaxLines (1 );
183+ titleTextView .setLayoutParams (new LinearLayout .LayoutParams (ViewGroup .LayoutParams .WRAP_CONTENT , ViewGroup .LayoutParams .WRAP_CONTENT ));
184+
185+ this .setupItem (tabItemLayout , titleTextView , iconImageView , tabItem );
186+
187+ tabItemLayout .addView (iconImageView );
188+ tabItemLayout .addView (titleTextView );
189+ return tabItemLayout ;
190+ }
191+
192+ private void setupItem (LinearLayout ll , TextView textView ,ImageView imgView , TabItemSpec tabItem ){
193+ float density = getResources ().getDisplayMetrics ().density ;
194+ if (tabItem .iconId != 0 ) {
195+ imgView .setImageResource (tabItem .iconId );
196+ imgView .setVisibility (VISIBLE );
197+ } else if (tabItem .iconDrawable != null ) {
198+ imgView .setImageDrawable (tabItem .iconDrawable );
199+ imgView .setVisibility (VISIBLE );
200+ } else {
201+ imgView .setVisibility (GONE );
202+ }
203+
204+ if (tabItem .title != null && !tabItem .title .isEmpty ()) {
205+ textView .setText (tabItem .title );
206+ textView .setVisibility (VISIBLE );
207+
208+ if (tabItem .typeFace != null ) {
209+ textView .setTypeface (tabItem .typeFace );
210+ }
211+
212+ if (tabItem .fontSize != 0 ) {
213+ textView .setTextSize (tabItem .fontSize );
214+ }
215+
216+ if (tabItem .color != 0 ) {
217+ textView .setTextColor (tabItem .color );
218+ mTabStrip .setShouldUpdateTabsTextColor (false );
219+ }
220+ } else {
221+ textView .setVisibility (GONE );
222+ }
223+
224+ if (tabItem .backgroundColor != 0 ) {
225+ ll .setBackgroundColor (tabItem .backgroundColor );
226+ }
227+
228+ ll .setMinimumHeight ((int ) (BOTTOM_NAV_HEIGHT * density ));
229+
230+ LinearLayout .LayoutParams lp = (LinearLayout .LayoutParams ) ll .getLayoutParams ();
231+ lp .width = 0 ;
232+ lp .weight = 1 ;
233+ }
234+
235+ public boolean onTap (int position ) {
236+ // to be overridden in JS
237+ return true ;
238+ }
239+
240+ public void onSelectedPositionChange (int position , int prevPosition ) {
241+ // to be overridden in JS
242+ }
243+
244+ private void setImageHeights (){
245+ if (this .mTabItems != null ) {
246+ for (TabItemSpec tabItem : this .mTabItems ) {
247+ if (tabItem .imageHeight == 0 && tabItem .iconId != 0 ) {
248+ Drawable drawable = getResources ().getDrawable (tabItem .iconId );
249+ tabItem .imageHeight = drawable .getIntrinsicHeight ();
250+ }
251+ if (tabItem .imageHeight > this .mMaxImageHeight ) {
252+ this .mMaxImageHeight = tabItem .imageHeight ;
253+ }
254+ }
255+ }
256+ }
257+
258+ private void populateTabStrip () {
259+ final OnClickListener tabClickListener = new TabClickListener ();
260+
261+ if (this .mTabItems != null ) {
262+ int count = this .mTabItems .length < 5 ? this .mTabItems .length : 5 ;
263+ for (int i = 0 ; i < count ; i ++) {
264+ TabItemSpec tabItem ;
265+ tabItem = this .mTabItems [i ];
266+ View tabView = createDefaultTabView (getContext (), tabItem );
267+ tabView .setOnClickListener (tabClickListener );
268+
269+ String desc = mContentDescriptions .get (i , null );
270+ if (desc != null ) {
271+ tabView .setContentDescription (desc );
272+ }
273+
274+ mTabStrip .addView (tabView );
275+ }
276+ int tabTextColor = mTabStrip .getTabTextColor ();
277+ mTabStrip .setTabTextColor (Color .argb (100 , Color .red (tabTextColor ), Color .green (tabTextColor ), Color .blue (tabTextColor )));
278+ mTabStrip .setSelectedTabTextColor (Color .argb (255 , Color .red (tabTextColor ), Color .green (tabTextColor ), Color .blue (tabTextColor )));
279+ }
280+ }
281+
282+ public void setSelectedPosition (int position ) {
283+ int prevPosition = mTabStrip .getSelectedPosition ();
284+ if (prevPosition == position ) {
285+ return ;
286+ }
287+
288+ mTabStrip .setSelectedPosition (position );
289+ onSelectedPositionChange (position , prevPosition );
290+ }
291+
292+ public void setContentDescription (int i , String desc ) {
293+ mContentDescriptions .put (i , desc );
294+ }
295+
296+ private class TabClickListener implements OnClickListener {
297+ @ Override
298+ public void onClick (View v ) {
299+ for (int i = 0 ; i < mTabStrip .getChildCount (); i ++) {
300+ if (v == mTabStrip .getChildAt (i )) {
301+ if (onTap (i )) {
302+ setSelectedPosition (i );
303+ }
304+ return ;
305+ }
306+ }
307+ }
308+ }
309+ }
0 commit comments