[关闭]
@coder-pig 2015-08-28T17:24:31.000000Z 字数 9355 阅读 1657

Android基础入门教程——5.2.1 Fragment实例精讲——底部导航栏的实现(方法1)

Android基础入门教程


本节引言:

在上一节中我们对Fragment进行了一个初步的了解,学习了概念,生命周期,Fragment管理与
Fragment事务,以及动态与静态加载Fragment。从本节开始我们会讲解一些Fragment在实际开发
中的一些实例!而本节给大家讲解的是底部导航栏的实现!而基本的底部导航栏方法有很多种,
比如全用TextView做,或者用RadioButton,又或者使用TabLayout + RadioButton,当然复杂
的情况还是得走外层套布局的方法!本节我们用TextView来做一个底部导航栏的效果,也熟悉
下Fragment的使用!好的,开始本节内容!


1.要实现的效果图以及工程目录结构:

先看看效果图吧:

接着看看我们的工程的目录结构


2.实现流程:


Step 1:写下底部选项的一些资源文件

我们从图上可以看到,我们底部的每一项点击的时候都有不同的效果是吧!
我们是通过是否selected来判定的!我们要写的资源文件有:首先是图片,然后是文字,接着是背景!

图片Drawable资源:tab_menu_channel.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">
  3. <item android:drawable="@mipmap/tab_channel_pressed" android:state_selected="true" />
  4. <item android:drawable="@mipmap/tab_channel_normal" />
  5. </selector>

其他三个照葫芦画瓢!

文字资源:tab_menu_text.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">
  3. <item android:color="@color/text_yellow" android:state_selected="true" />
  4. <item android:color="@color/text_gray" />
  5. </selector>

背景资源:tab_menu_bg.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">
  3. <item android:state_selected="true">
  4. <shape>
  5. <solid android:color="#FFC4C4C4" />
  6. </shape>
  7. </item>
  8. <item>
  9. <shape>
  10. <solid android:color="@color/transparent" />
  11. </shape>
  12. </item>
  13. </selector>

Step 2:编写我们的Activity布局

activity_main.xml:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. tools:context=".MainActivity">
  6. <RelativeLayout
  7. android:id="@+id/ly_top_bar"
  8. android:layout_width="match_parent"
  9. android:layout_height="48dp"
  10. android:background="@color/bg_topbar">
  11. <TextView
  12. android:id="@+id/txt_topbar"
  13. android:layout_width="match_parent"
  14. android:layout_height="match_parent"
  15. android:layout_centerInParent="true"
  16. android:gravity="center"
  17. android:textSize="18sp"
  18. android:textColor="@color/text_topbar"
  19. android:text="信息"/>
  20. <View
  21. android:layout_width="match_parent"
  22. android:layout_height="2px"
  23. android:background="@color/div_white"
  24. android:layout_alignParentBottom="true"/>
  25. </RelativeLayout>
  26. <LinearLayout
  27. android:id="@+id/ly_tab_bar"
  28. android:layout_width="match_parent"
  29. android:layout_height="56dp"
  30. android:layout_alignParentBottom="true"
  31. android:background="@color/bg_white"
  32. android:orientation="horizontal">
  33. <TextView
  34. android:id="@+id/txt_channel"
  35. android:layout_width="0dp"
  36. android:layout_height="match_parent"
  37. android:layout_weight="1"
  38. android:background="@drawable/tab_menu_bg"
  39. android:drawablePadding="3dp"
  40. android:drawableTop="@drawable/tab_menu_channel"
  41. android:gravity="center"
  42. android:padding="5dp"
  43. android:text="@string/tab_menu_alert"
  44. android:textColor="@drawable/tab_menu_text"
  45. android:textSize="16sp" />
  46. <TextView
  47. android:id="@+id/txt_message"
  48. android:layout_width="0dp"
  49. android:layout_height="match_parent"
  50. android:layout_weight="1"
  51. android:background="@drawable/tab_menu_bg"
  52. android:drawablePadding="3dp"
  53. android:drawableTop="@drawable/tab_menu_message"
  54. android:gravity="center"
  55. android:padding="5dp"
  56. android:text="@string/tab_menu_profile"
  57. android:textColor="@drawable/tab_menu_text"
  58. android:textSize="16sp" />
  59. <TextView
  60. android:id="@+id/txt_better"
  61. android:layout_width="0dp"
  62. android:layout_height="match_parent"
  63. android:layout_weight="1"
  64. android:background="@drawable/tab_menu_bg"
  65. android:drawablePadding="3dp"
  66. android:drawableTop="@drawable/tab_menu_better"
  67. android:gravity="center"
  68. android:padding="5dp"
  69. android:text="@string/tab_menu_pay"
  70. android:textColor="@drawable/tab_menu_text"
  71. android:textSize="16sp" />
  72. <TextView
  73. android:id="@+id/txt_setting"
  74. android:layout_width="0dp"
  75. android:layout_height="match_parent"
  76. android:layout_weight="1"
  77. android:background="@drawable/tab_menu_bg"
  78. android:drawablePadding="3dp"
  79. android:drawableTop="@drawable/tab_menu_setting"
  80. android:gravity="center"
  81. android:padding="5dp"
  82. android:text="@string/tab_menu_setting"
  83. android:textColor="@drawable/tab_menu_text"
  84. android:textSize="16sp"/>
  85. </LinearLayout>
  86. <View
  87. android:id="@+id/div_tab_bar"
  88. android:layout_width="match_parent"
  89. android:layout_height="2px"
  90. android:background="@color/div_white"
  91. android:layout_above="@id/ly_tab_bar"/>
  92. <FrameLayout
  93. android:layout_width="match_parent"
  94. android:layout_height="match_parent"
  95. android:layout_below="@id/ly_top_bar"
  96. android:layout_above="@id/div_tab_bar"
  97. android:id="@+id/ly_content">
  98. </FrameLayout>
  99. </RelativeLayout>

代码解析:

首先定义顶部标题栏的样式,48dp的LinearLayout中间加上一个TextView作为标题!
接着定义一个大小为56dp的LinerLayout对其底部,在这个里面加入四个TextView,比例1:1:1:1,
并且设置相关属性,接着在这个LinearLayout上加一条线段!
最后以标题栏和底部导航栏为边界,写一个FrameLayout,宽高match_parent,用做Fragment的容器!

PS:这里四个TextView属性是重复的,你也可以自行抽取出来,编写一个style,设置下~


Step 3:隐藏顶部导航栏

意外发现以前的在Activity中调用requestWindowFeature(Window.FEATURE_NO_TITLE);可以隐藏手机
自带顶部导航栏,但是写demo时候发现会报错,即使这句话写在了setContentView()之前!可能是因为
继承的是AppCompatActivity而非Activity类!
当然以前的getSupportActionbar().hide()隐藏掉Actionbar,但是他还是会在界面上!
最后还有一种方法就是自己编写一个style,然后在AndroidManifest.xml中为Application设置这个Theme:

style.xml中加上:

  1. <style name="Theme.AppCompat.NoActionBar">
  2. <item name="windowActionBar">false</item>
  3. <item name="windowNoTitle">true</item>
  4. </style>

PS:上述“良心代码”由好程序员曹神赞助~

接着AndroidManifest.xml设置下theme属性:

  1. android:theme="@style/Theme.AppCompat.NoActionBar"

Step 4:创建一个Fragment的简单布局与类:

fg_content.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical" android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:background="@color/bg_white">
  6. <TextView
  7. android:id="@+id/txt_content"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent"
  10. android:gravity="center"
  11. android:text="呵呵"
  12. android:textColor="@color/text_yellow"
  13. android:textSize="20sp"/>
  14. </LinearLayout>

MyFragment.java:

  1. /**
  2. * Created by Coder-pig on 2015/8/28 0028.
  3. */
  4. public class MyFragment extends Fragment {
  5. private String content;
  6. public MyFragment(String content) {
  7. this.content = content;
  8. }
  9. @Override
  10. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  11. View view = inflater.inflate(R.layout.fg_content,container,false);
  12. TextView txt_content = (TextView) view.findViewById(R.id.txt_content);
  13. txt_content.setText(content);
  14. return view;
  15. }
  16. }

代码解析:

就是简单的重写了一个onCreateView()方法,其他方法可以按需重写!


Step 5:编写MainActivity.java

先说说我们要考虑的一些关键问题:

  • Fragment什么时候初始化和add到容器中?什么时候hide和show?
  • 如何让TextView被选中?选中一个TextView后,要做一些什么操作?
  • 刚进入MainActivity怎么样让一个TextView处于Selected的状态?

嗯,接下来一一解答上面这些问题:

  • 我们选中TextView后对对应的Fragment进行判空,如果为空,初始化,并添加到容器中;
    而hide的话,我们定义一个方法hide所有的Fragment,每次触发点击事件就先调用这个hideAll方法,
    讲所有Fragment隐藏起来,然后如果TextView对应的Fragment不为空,我们就将这个Fragment显示出来;
  • 这个我们通过点击事件来实现,点击TextView后先重置所有TextView的选中状态为false,然后设置点击的
    TextView的选中状态为true;
  • 这个更简单,我们是通过点击事件来设置选中的,那么在onCreate()方法里加个触发点击事件的
    方法不就可以了嘛~ txt_channel.performClick();

逻辑都弄懂了,直接上代码咯:

MainActivity.java:

  1. /**
  2. * Created by Coder-pig on 2015/8/28 0028.
  3. */
  4. public class MainActivity extends AppCompatActivity implements View.OnClickListener{
  5. //UI Object
  6. private TextView txt_topbar;
  7. private TextView txt_channel;
  8. private TextView txt_message;
  9. private TextView txt_better;
  10. private TextView txt_setting;
  11. private FrameLayout ly_content;
  12. //Fragment Object
  13. private MyFragment fg1,fg2,fg3,fg4;
  14. private FragmentManager fManager;
  15. @Override
  16. protected void onCreate(Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. requestWindowFeature(Window.FEATURE_NO_TITLE);
  19. setContentView(R.layout.activity_main);
  20. fManager = getFragmentManager();
  21. bindViews();
  22. txt_channel.performClick(); //模拟一次点击,既进去后选择第一项
  23. }
  24. //UI组件初始化与事件绑定
  25. private void bindViews() {
  26. txt_topbar = (TextView) findViewById(R.id.txt_topbar);
  27. txt_channel = (TextView) findViewById(R.id.txt_channel);
  28. txt_message = (TextView) findViewById(R.id.txt_message);
  29. txt_better = (TextView) findViewById(R.id.txt_better);
  30. txt_setting = (TextView) findViewById(R.id.txt_setting);
  31. ly_content = (FrameLayout) findViewById(R.id.ly_content);
  32. txt_channel.setOnClickListener(this);
  33. txt_message.setOnClickListener(this);
  34. txt_better.setOnClickListener(this);
  35. txt_setting.setOnClickListener(this);
  36. }
  37. //重置所有文本的选中状态
  38. private void setSelected(){
  39. txt_channel.setSelected(false);
  40. txt_message.setSelected(false);
  41. txt_better.setSelected(false);
  42. txt_setting.setSelected(false);
  43. }
  44. //隐藏所有Fragment
  45. private void hideAllFragment(FragmentTransaction fragmentTransaction){
  46. if(fg1 != null)fragmentTransaction.hide(fg1);
  47. if(fg2 != null)fragmentTransaction.hide(fg2);
  48. if(fg3 != null)fragmentTransaction.hide(fg3);
  49. if(fg4 != null)fragmentTransaction.hide(fg4);
  50. }
  51. @Override
  52. public void onClick(View v) {
  53. FragmentTransaction fTransaction = fManager.beginTransaction();
  54. hideAllFragment(fTransaction);
  55. switch (v.getId()){
  56. case R.id.txt_channel:
  57. setSelected();
  58. txt_channel.setSelected(true);
  59. if(fg1 == null){
  60. fg1 = new MyFragment("第一个Fragment");
  61. fTransaction.add(R.id.ly_content,fg1);
  62. }else{
  63. fTransaction.show(fg1);
  64. }
  65. break;
  66. case R.id.txt_message:
  67. setSelected();
  68. txt_message.setSelected(true);
  69. if(fg2 == null){
  70. fg2 = new MyFragment("第二个Fragment");
  71. fTransaction.add(R.id.ly_content,fg2);
  72. }else{
  73. fTransaction.show(fg2);
  74. }
  75. break;
  76. case R.id.txt_better:
  77. setSelected();
  78. txt_better.setSelected(true);
  79. if(fg3 == null){
  80. fg3 = new MyFragment("第三个Fragment");
  81. fTransaction.add(R.id.ly_content,fg3);
  82. }else{
  83. fTransaction.show(fg3);
  84. }
  85. break;
  86. case R.id.txt_setting:
  87. setSelected();
  88. txt_setting.setSelected(true);
  89. if(fg4 == null){
  90. fg4 = new MyFragment("第四个Fragment");
  91. fTransaction.add(R.id.ly_content,fg4);
  92. }else{
  93. fTransaction.show(fg4);
  94. }
  95. break;
  96. }
  97. fTransaction.commit();
  98. }
  99. }

3.代码下载:

FragmentDemo.ziphttp://pan.baidu.com/s/1jGivCe6
声明:图片素材来自App:better,本代码只做演示,并无用于商业用途!


4.本节小结

本节给大家讲解了如何使用一个LinarLayout + 四个TextView 实现一个底部导航栏以及
Fragment add,hide,show的逻辑~还是蛮简单的,最后要感谢小猪秘密基地的基神,B神,
还有好程序员曹神给我的一些指点!万分感谢,仅以此篇纪念小猪重返装逼界,嗯,重
返应用层,嘿嘿,本节就到这里,谢谢~

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注