Fragment 底部导航栏红点
前两章节我们使用了两种方法来实现底部导航栏,但是,这些导航栏都只是最基本的情况,如果要像微信那样,想在底部导航栏上的 item 带有一个红色的小点,然后加上一个消息数目这样, 前面两种方案就显得无力了
微信底部导航栏
我们先来看看微信是怎么实现的?,打开手机的开发者选项,勾选里面的: 显示布局边界 ,然后打开微信,可以看到底部导航栏是这样的:
从上图中我们可以看出,微信底部导航栏不是简单的 TextView
或者 RadioGroup
构成的
我能想到的方案就是:外层一个 LinearLayout
,中间一个 RelativeLayout
,而在中间有一个 TextView
,
然后再在 TextView
的右上角有一个红色圆圈背景的 TextView
或者一个红色的小点
红色小点平时的时候应该设置的不可见,当收到信息推送,即有相关类别信息的时候再可见,并且显示对应的信息数目
范例
接下来,按照我们的思路,使用 Fragment+RadioButton
实现一次吧
-
创建一个 空的 Android 项目
cn.twle.android.FragmentRedDot
-
下载解压 /static/i/android/fragment_tab_demo.zip,并把所有的图片拖到
res/drawable
目录下 -
在
res/drawable
目录下新建四个文件tab_menu_home.xml
<?xml version="1.0" encoding="utf-8" ?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/tab_home_pressed" android:state_selected="true" /> <item android:drawable="@drawable/tab_home" /> </selector>
tab_menu_category.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/tab_category_pressed" android:state_selected="true" /> <item android:drawable="@drawable/tab_category" /> </selector>
tab_menu_cart.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/tab_cart_pressed" android:state_selected="true" /> <item android:drawable="@drawable/tab_cart" /> </selector>
tab_menu_discover.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/tab_discover_pressed" android:state_selected="true" /> <item android:drawable="@drawable/tab_discover" /> </selector>
-
在
res/drawable
目录下新建文件tab_menu_text.xml
创建文字资源因为文字也会根据是否选中而改变颜色
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="#1296db" android:state_selected="true" /> <item android:color="#515151" /> </selector>
-
在
res/drawable
目录下新建文件tab_menu_bg.xml
创建背景资源选中的 tab 背景会有点灰色
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true"> <shape> <solid android:color="#ffdddddd" /> </shape> </item> <item> <shape> <solid android:color="#00FFFFFF" /> </shape> </item> </selector>
-
在
res/layout
目录下创建一个Fragment
的简单布局 fg_content.xml<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="5dp"> <Button android:id="@+id/btn_one" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="第一个显示信息"/> <Button android:id="@+id/btn_two" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="第二个显示信息"/> <Button android:id="@+id/btn_three" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="第三个显示信息"/> <Button android:id="@+id/btn_four" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="第四个显示信息"/> <TextView android:id="@+id/ms_txt_content" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="简单教程,简单编程" android:textColor="#333333" android:textSize="20sp"/> </LinearLayout>
-
创建底部导航栏通用样式
因为四个选项的 TextView 以及右上角的红点数字属性都差不多
<TextView android:id="@+id/tab_menu_home" android:layout_marginTop="5dp" android:layout_width="wrap_content" android:layout_height="48dp" android:layout_centerInParent="true" android:textColor="@drawable/tab_menu_text" android:drawableTop="@drawable/tab_menu_home" android:text="@首页"/> <TextView android:layout_width="20dp" android:layout_height="20dp" android:background="##ff0000" android:layout_toRightOf="@+id/tab_menu_home" android:layout_marginLeft="-10dp" android:text="99+" android:textSize="12sp" android:gravity="center" android:textColor="#ffffff"/>
我们将他们抽取出来,添加 到
styles.xml
里<style name="tab_menu_text"> <item name="android:layout_marginTop">5dp</item> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">48dp</item> <item name="android:layout_centerInParent">true</item> <item name="android:textColor">@drawable/tab_menu_text</item> </style> <style name="tab_menu_bgnum"> <item name="android:layout_width">20dp</item> <item name="android:layout_height">20dp</item> <item name="android:background">@drawable/bg_num</item> <item name="android:layout_marginLeft">-10dp</item> <item name="android:textSize">12sp</item> <item name="android:gravity">center</item> <item name="android:textColor">#ffffff</item> </style>
-
隐藏顶部导航栏
修改
MainActivity.java
继承自Activity
而非AppCompatActivity
然后在
onCreate()
方法中的super.onCreate(savedInstanceState);
之前加上下列代码requestWindowFeature(Window.FEATURE_NO_TITLE);
最后在 AndroidManifest.xml 设置下 theme 属性
android:theme="@style/Theme.AppCompat.NoActionBar"
注意
把
requestWindowFeature(Window.FEATURE_NO_TITLE);
放在super.onCreate(savedInstanceState);
前面就可以隐藏ActionBar
而不报错 -
修改
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:id="@+id/ms_topbar" android:layout_width="match_parent" android:layout_height="48dp" android:background="#FCFCFC"> <TextView android:id="@+id/ms_topbar_title" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true" android:gravity="center" android:textSize="18sp" android:textColor="#694E42" android:text="信息"/> <View android:layout_width="match_parent" android:layout_height="2px" android:background="#E5E5E5" android:layout_alignParentBottom="true"/> </RelativeLayout> <LinearLayout android:id="@+id/ms_tab_bar" android:layout_width="match_parent" android:layout_height="56dp" android:layout_alignParentBottom="true" android:orientation="horizontal"> <LinearLayout android:id="@+id/ms_tab_menu_home" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center"> <RelativeLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:padding="5dp"> <TextView android:id="@+id/tab_menu_home" style="@style/tab_menu_text" android:drawableTop="@drawable/tab_menu_home" android:text="首页" /> <TextView android:id="@+id/tab_menu_home_num" style="@style/tab_menu_bgnum" android:layout_toRightOf="@+id/tab_menu_home" android:text="99+" android:visibility="gone" /> </RelativeLayout> </LinearLayout> <LinearLayout android:id="@+id/ms_tab_menu_category" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center"> <RelativeLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:padding="5dp"> <TextView android:id="@+id/tab_menu_category" style="@style/tab_menu_text" android:drawableTop="@drawable/tab_menu_category" android:text="分类" /> <TextView android:id="@+id/tab_menu_category_num" style="@style/tab_menu_bgnum" android:layout_toRightOf="@+id/tab_menu_category" android:text="99+" android:visibility="gone" /> </RelativeLayout> </LinearLayout> <LinearLayout android:id="@+id/ms_tab_menu_discover" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center"> <RelativeLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:padding="5dp"> <TextView android:id="@+id/tab_menu_discover" style="@style/tab_menu_text" android:drawableTop="@drawable/tab_menu_discover" android:text="发现" /> <TextView android:id="@+id/tab_menu_discover_num" style="@style/tab_menu_bgnum" android:layout_toRightOf="@+id/tab_menu_discover" android:text="99+" android:visibility="gone" /> </RelativeLayout> </LinearLayout> <LinearLayout android:id="@+id/ms_tab_menu_cart" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center"> <RelativeLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:padding="5dp"> <TextView android:id="@+id/tab_menu_cart" style="@style/tab_menu_text" android:drawableTop="@drawable/tab_menu_cart" android:text="购物车" /> <ImageView android:id="@+id/tab_menu_cart_partner" android:layout_width="12dp" android:layout_height="12dp" android:layout_marginLeft="-5dp" android:layout_toRightOf="@id/tab_menu_cart" android:visibility="gone" android:src="@drawable/partner_red" /> </RelativeLayout> </LinearLayout> </LinearLayout> <View android:id="@+id/div_tab_bar" android:layout_width="match_parent" android:layout_height="2px" android:background="#E5E5E5" android:layout_above="@id/ms_tab_bar"/> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/ms_topbar" android:layout_above="@id/div_tab_bar" android:id="@+id/ms_content"> </FrameLayout> </RelativeLayout>
-
在
MainActivity.java
同一个目录下新建文件MsFragment.java
通过
getActivity.findViewById()
来获得Activity
中的小红点package cn.twle.android.fragmentreddot; import android.annotation.SuppressLint; import android.app.Fragment; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; @SuppressLint("ValidFragment") public class MsFragment extends Fragment implements View.OnClickListener{ private Context mContext; private Button btn_one; private Button btn_two; private Button btn_three; private Button btn_four; public MsFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fg_content,container,false); //UI Object btn_one = (Button) view.findViewById(R.id.btn_one); btn_two = (Button) view.findViewById(R.id.btn_two); btn_three = (Button) view.findViewById(R.id.btn_three); btn_four = (Button) view.findViewById(R.id.btn_four); //Bind Event btn_one.setOnClickListener(this); btn_two.setOnClickListener(this); btn_three.setOnClickListener(this); btn_four.setOnClickListener(this); return view; } @Override public void onClick(View v) { switch (v.getId()){ case R.id.btn_one: TextView tab_menu_home_num = (TextView) getActivity ().findViewById(R.id.tab_menu_home_num); tab_menu_home_num.setText("11"); tab_menu_home_num.setVisibility(View.VISIBLE); break; case R.id.btn_two: TextView tab_menu_category_num = (TextView) getActivity ().findViewById(R.id.tab_menu_category_num); tab_menu_category_num.setText("20"); tab_menu_category_num.setVisibility(View.VISIBLE); break; case R.id.btn_three: TextView tab_menu_discover_num = (TextView) getActivity ().findViewById(R.id.tab_menu_discover_num); tab_menu_discover_num.setText("99+"); tab_menu_discover_num.setVisibility(View.VISIBLE); break; case R.id.btn_four: ImageView tab_menu_cart_partner = (ImageView) getActivity ().findViewById(R.id.tab_menu_cart_partner); tab_menu_cart_partner.setVisibility(View.VISIBLE); break; } } }
-
修改
MainActivity.java
package cn.twle.android.fragmentreddot; import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; public class MainActivity extends Activity implements View.OnClickListener { //Activity UI Object private LinearLayout ms_tab_menu_home; private TextView tab_menu_home; private TextView tab_menu_home_num; private LinearLayout ms_tab_menu_category; private TextView tab_menu_category; private TextView tab_menu_category_num; private LinearLayout ms_tab_menu_discover; private TextView tab_menu_discover; private TextView tab_menu_discover_num; private LinearLayout ms_tab_menu_cart; private TextView tab_menu_cart; private ImageView tab_menu_cart_partner; private FragmentManager fManager; private FragmentTransaction fTransaction; private MsFragment fg1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindViews(); ms_tab_menu_home.performClick(); fg1 = new MsFragment(); fManager = getFragmentManager(); fTransaction = fManager.beginTransaction(); fTransaction.add(R.id.ms_content, fg1).commit(); } private void bindViews() { ms_tab_menu_home = (LinearLayout) findViewById(R.id.ms_tab_menu_home); tab_menu_home = (TextView) findViewById(R.id.tab_menu_home); tab_menu_home_num = (TextView) findViewById(R.id.tab_menu_home_num); ms_tab_menu_category = (LinearLayout) findViewById(R.id.ms_tab_menu_category); tab_menu_category = (TextView) findViewById(R.id.tab_menu_category); tab_menu_category_num = (TextView) findViewById(R.id.tab_menu_category_num); ms_tab_menu_discover = (LinearLayout) findViewById(R.id.ms_tab_menu_discover); tab_menu_discover = (TextView) findViewById(R.id.tab_menu_discover); tab_menu_discover_num = (TextView) findViewById(R.id.tab_menu_discover_num); ms_tab_menu_cart = (LinearLayout) findViewById(R.id.ms_tab_menu_cart); tab_menu_cart = (TextView) findViewById(R.id.tab_menu_cart); tab_menu_cart_partner = (ImageView) findViewById(R.id.tab_menu_cart_partner); ms_tab_menu_home.setOnClickListener(this); ms_tab_menu_category.setOnClickListener(this); ms_tab_menu_discover.setOnClickListener(this); ms_tab_menu_cart.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.ms_tab_menu_home: setSelected(); tab_menu_home.setSelected(true); tab_menu_home_num.setVisibility(View.INVISIBLE); break; case R.id.ms_tab_menu_category: setSelected(); tab_menu_category.setSelected(true); tab_menu_category_num.setVisibility(View.INVISIBLE); break; case R.id.ms_tab_menu_discover: setSelected(); tab_menu_discover.setSelected(true); tab_menu_discover_num.setVisibility(View.INVISIBLE); break; case R.id.ms_tab_menu_cart: setSelected(); tab_menu_cart.setSelected(true); tab_menu_cart_partner.setVisibility(View.INVISIBLE); break; } } //重置所有文本的选中状态 private void setSelected() { tab_menu_home.setSelected(false); tab_menu_category.setSelected(false); tab_menu_discover.setSelected(false); tab_menu_cart.setSelected(false); } }