当前位置:   article > 正文

android中实现底部导航栏

android中实现底部导航栏

1、引言

        底部导航栏在app应用中是十分常见了,大部分的安卓应用中也都实现了底部导航栏的功能,这里我就以我以前做的一个简单小说阅读软件为例,为大家演示一下底部导航栏的使用,需要的朋友直接复制代码过去改写就行了。

2、代码实现

2.1、主界面布局

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:orientation="vertical"
  8. tools:context=".MainActivity">
  9. <FrameLayout
  10. android:id="@+id/fl_content"
  11. android:layout_width="match_parent"
  12. android:layout_height="wrap_content"
  13. android:layout_weight="1" />
  14. <RadioGroup
  15. android:id="@+id/rg_main"
  16. android:layout_width="match_parent"
  17. android:layout_height="wrap_content"
  18. android:background="#f5f5f5"
  19. android:gravity="center_vertical"
  20. android:orientation="horizontal"
  21. android:padding="3dp">
  22. <!--书架-->
  23. <com.kotlin.custom.DrawableRadioButton
  24. android:id="@+id/rb_main_book"
  25. style="@style/bottom_tag_style"
  26. android:text="书架"
  27. app:drawableSize="30dp"
  28. android:clickable="true"
  29. app:drawableTop="@drawable/book_drawable_selector" />
  30. <!--书城-->
  31. <com.kotlin.custom.DrawableRadioButton
  32. android:id="@+id/rb_main_store"
  33. style="@style/bottom_tag_style"
  34. android:text="书城"
  35. android:clickable="true"
  36. app:drawableSize="30dp"
  37. app:drawableTop="@drawable/store_drawable_selector" />
  38. <!--我的-->
  39. <com.kotlin.custom.DrawableRadioButton
  40. android:id="@+id/rb_main_user"
  41. style="@style/bottom_tag_style"
  42. android:text="我的"
  43. android:clickable="true"
  44. app:drawableSize="30dp"
  45. app:drawableTop="@drawable/user_drawable_selector" />
  46. </RadioGroup>
  47. </LinearLayout>

2.2、主界面代码

        这里包含了一些进行操作实际功能的代码,大家复制时直接忽略就行。

  1. package com.kotlin.novel;
  2. import androidx.annotation.NonNull;
  3. import androidx.fragment.app.Fragment;
  4. import androidx.fragment.app.FragmentActivity;
  5. import androidx.fragment.app.FragmentTransaction;
  6. import android.content.Intent;
  7. import android.content.pm.ActivityInfo;
  8. import android.graphics.Color;
  9. import android.os.Bundle;
  10. import android.os.Handler;
  11. import android.os.Message;
  12. import android.view.Gravity;
  13. import android.view.KeyEvent;
  14. import android.view.View;
  15. import android.widget.RadioGroup;
  16. import android.widget.Toast;
  17. import com.google.gson.Gson;
  18. import com.kotlin.base.BaseFragment;
  19. import com.kotlin.data.UpdateVersion;
  20. import com.kotlin.dialog.UpdateDialogActivity;
  21. import com.kotlin.fragment.BookShelfFragment;
  22. import com.kotlin.fragment.BookStoreFragment;
  23. import com.kotlin.fragment.UserFragment;
  24. import com.kotlin.utils.ServerUtils;
  25. import com.kotlin.utils.SetUiSize;
  26. import java.io.ByteArrayOutputStream;
  27. import java.io.InputStream;
  28. import java.net.HttpURLConnection;
  29. import java.net.URL;
  30. import java.util.ArrayList;
  31. import java.util.List;
  32. /**
  33. * 主界面导航切换,如果需要添加界面来这里修改
  34. */
  35. public class MainActivity extends FragmentActivity {
  36. @Override
  37. protected void onResume() {//强制竖屏
  38. if (getRequestedOrientation()!=ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){
  39. setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
  40. }
  41. super.onResume();
  42. }
  43. public static MainActivity activity;
  44. public RadioGroup rg_main;
  45. private List<BaseFragment> baseFragment;
  46. private int position;//选中的Fragment的对应的位置
  47. private Fragment fragment;//上次切换的Fragment
  48. @Override
  49. protected void onCreate(Bundle savedInstanceState) {
  50. super.onCreate(savedInstanceState);
  51. setContentView(R.layout.activity_main);
  52. View decorView=getWindow().getDecorView();//获取当前界面的DecorView
  53. int option=View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
  54. View.SYSTEM_UI_FLAG_LAYOUT_STABLE |//全屏隐藏状态栏
  55. View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;//更改文字颜色为深黑色
  56. decorView.setSystemUiVisibility(option);//设置系统UI元素的可见性
  57. getWindow().setNavigationBarColor(Color.TRANSPARENT);
  58. getWindow().setStatusBarColor(Color.TRANSPARENT);//将状态栏设置为透明色
  59. rg_main = findViewById(R.id.rg_main);
  60. initFragment();
  61. setListener();
  62. activity=this;
  63. updateVersion();
  64. }
  65. private void setListener() {
  66. rg_main.setOnCheckedChangeListener(new CheckedChangeListener());
  67. //设置默认选中书架
  68. rg_main.check(R.id.rb_main_book);
  69. }
  70. class CheckedChangeListener implements RadioGroup.OnCheckedChangeListener {
  71. @Override
  72. public void onCheckedChanged(RadioGroup group, int checkedId) {
  73. switch (checkedId){
  74. case R.id.rb_main_book://书架
  75. position = 0;
  76. break;
  77. case R.id.rb_main_store://书城
  78. position = 1;
  79. break;
  80. case R.id.rb_main_user://我的
  81. position = 2;
  82. break;
  83. }
  84. //根据位置得到对应的Fragment
  85. BaseFragment to = getFragment();
  86. //替换
  87. switchFrament(fragment,to);
  88. }
  89. }
  90. /**
  91. * @param from 刚显示的Fragment,马上就要被隐藏
  92. * @param to 马上要切换到的Fragment,马上就要被显示
  93. */
  94. private void switchFrament(Fragment from,Fragment to) {
  95. if(from != to){
  96. fragment = to;
  97. FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
  98. //判断有没有被添加,才切换
  99. if(!to.isAdded()){
  100. //to没有被添加
  101. //from隐藏
  102. if(from != null){
  103. ft.hide(from);
  104. }
  105. //添加to
  106. if(to != null){
  107. ft.add(R.id.fl_content,to).commit();
  108. }
  109. }else{
  110. //to已经被添加
  111. // from隐藏
  112. if(from != null){
  113. ft.hide(from);
  114. }
  115. //显示to
  116. if(to != null){
  117. ft.show(to).commit();
  118. }
  119. }
  120. }
  121. }
  122. /**
  123. * 根据位置得到对应的Fragment
  124. * @return
  125. */
  126. private BaseFragment getFragment() {
  127. BaseFragment fragment = baseFragment.get(position);
  128. return fragment;
  129. }
  130. private void initFragment() {
  131. baseFragment = new ArrayList<>();
  132. baseFragment.add(new BookShelfFragment());//书架Fragment
  133. baseFragment.add(new BookStoreFragment());//书城Fragment
  134. baseFragment.add(new UserFragment());//我的Fragment
  135. }
  136. public boolean exit;//标识是否可以退出
  137. @Override
  138. public boolean onKeyUp(int keyCode, KeyEvent event) {
  139. if(event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
  140. if(exit) {
  141. BookShelfFragment.fragment.handler.sendEmptyMessage(1);//刷新书架,取消选择
  142. return true;//不退出
  143. }
  144. }
  145. return super.onKeyUp(keyCode, event);
  146. }
  147. private String result;
  148. /**
  149. * 获取更新数据
  150. */
  151. private void updateVersion(){
  152. new Thread(){
  153. @Override
  154. public void run() {
  155. URL url;
  156. try {
  157. url=new URL(ServerUtils.updatePath);
  158. HttpURLConnection connection = (HttpURLConnection) url.openConnection();
  159. connection.setReadTimeout(5000);
  160. connection.setConnectTimeout(5000);
  161. int code = connection.getResponseCode();
  162. if (code==200){
  163. InputStream is = connection.getInputStream();
  164. ByteArrayOutputStream bs=new ByteArrayOutputStream();
  165. int len=-1;
  166. byte[] buffer=new byte[1024];
  167. while ((len=is.read(buffer))!=-1){
  168. bs.write(buffer,0,len);
  169. }
  170. result = bs.toString();
  171. bs.close();
  172. is.close();
  173. connection.disconnect();
  174. }
  175. } catch (Exception e) {
  176. }
  177. if (result!=null&&!result.equals("")){
  178. handler.sendEmptyMessage(0);
  179. }
  180. }
  181. }.start();
  182. }
  183. /**
  184. * 提示
  185. * @param message
  186. */
  187. private void tip(String message){
  188. runOnUiThread(() -> {
  189. //更改默认Toast显示方式,需要什么直接调用方法就行
  190. Toast toast=Toast.makeText(MainActivity.this,
  191. message,Toast.LENGTH_SHORT);
  192. int size= (int) (280/ SetUiSize.displayHeightDp*SetUiSize.displayHeight);
  193. toast.setGravity(Gravity.TOP,
  194. 0,size);
  195. toast.show();
  196. });
  197. }
  198. private Handler handler=new Handler(){
  199. @Override
  200. public void handleMessage(@NonNull Message msg) {
  201. super.handleMessage(msg);
  202. switch (msg.what){
  203. case 0:
  204. {
  205. UpdateVersion version = new Gson().fromJson(result, UpdateVersion.class);
  206. if (version.getApk_version()>ServerUtils.versionCode){
  207. Intent intent=new Intent(MainActivity.this, UpdateDialogActivity.class);
  208. intent.putExtra("result",result);
  209. startActivity(intent);
  210. }
  211. }
  212. break;
  213. }
  214. }
  215. };
  216. }

2.3、自定义控件

        自定义radiobutton:

  1. package com.kotlin.custom;
  2. import android.annotation.SuppressLint;
  3. import android.content.Context;
  4. import android.content.res.TypedArray;
  5. import android.graphics.drawable.Drawable;
  6. import android.util.AttributeSet;
  7. import android.widget.RadioButton;
  8. import com.kotlin.novel.R;
  9. /**
  10. * Describe:可控制drawableTop等图片的大小
  11. */
  12. @SuppressLint("AppCompatCustomView")
  13. public class DrawableRadioButton extends RadioButton {
  14. private int mDrawableSize;// xml文件中设置的大小
  15. public DrawableRadioButton(Context context) {
  16. this(context, null, 0);
  17. }
  18. public DrawableRadioButton(Context context, AttributeSet attrs) {
  19. this(context, attrs, 0);
  20. }
  21. public DrawableRadioButton(Context context, AttributeSet attrs, int defStyle) {
  22. super(context, attrs, defStyle);
  23. Drawable drawableLeft = null, drawableTop = null, drawableRight = null, drawableBottom = null;
  24. TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DrawableRadioButton);
  25. int n = a.getIndexCount();
  26. for (int i = 0; i < n; i++) {
  27. int attr = a.getIndex(i);
  28. switch (attr) {
  29. case R.styleable.DrawableRadioButton_drawableSize:
  30. mDrawableSize = a.getDimensionPixelSize(R.styleable.DrawableRadioButton_drawableSize, 50);
  31. break;
  32. case R.styleable.DrawableRadioButton_drawableTop:
  33. drawableTop = a.getDrawable(attr);
  34. break;
  35. case R.styleable.DrawableRadioButton_drawableBottom:
  36. drawableRight = a.getDrawable(attr);
  37. break;
  38. case R.styleable.DrawableRadioButton_drawableRight:
  39. drawableBottom = a.getDrawable(attr);
  40. break;
  41. case R.styleable.DrawableRadioButton_drawableLeft:
  42. drawableLeft = a.getDrawable(attr);
  43. break;
  44. }
  45. }
  46. a.recycle();
  47. setCompoundDrawablesWithIntrinsicBounds(drawableLeft, drawableTop, drawableRight, drawableBottom);
  48. }
  49. /**
  50. * RadioButton上、下、左、右设置图标
  51. */
  52. public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right, Drawable bottom) {
  53. if (left != null) {
  54. left.setBounds(0, 0, mDrawableSize, mDrawableSize);
  55. }
  56. if (right != null) {
  57. right.setBounds(0, 0, mDrawableSize, mDrawableSize);
  58. }
  59. if (top != null) {
  60. top.setBounds(0, 0, mDrawableSize, mDrawableSize);
  61. }
  62. if (bottom != null) {
  63. bottom.setBounds(0, 0, mDrawableSize, mDrawableSize);
  64. }
  65. setCompoundDrawables(left, top, right, bottom);
  66. }
  67. }

        自定义圆形图标。

  1. package com.kotlin.custom;
  2. import android.content.Context;
  3. import android.content.res.TypedArray;
  4. import android.graphics.*;
  5. import android.graphics.drawable.BitmapDrawable;
  6. import android.graphics.drawable.ColorDrawable;
  7. import android.graphics.drawable.Drawable;
  8. import android.util.AttributeSet;
  9. import com.kotlin.novel.R;
  10. public class CircleImageView extends androidx.appcompat.widget.AppCompatImageView {
  11. private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
  12. private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
  13. private static final int COLORDRAWABLE_DIMENSION = 1;
  14. private static final int DEFAULT_BORDER_WIDTH = 0;
  15. private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
  16. private final RectF mDrawableRect = new RectF();
  17. private final RectF mBorderRect = new RectF();
  18. private final Matrix mShaderMatrix = new Matrix();
  19. private final Paint mBitmapPaint = new Paint();
  20. private final Paint mBorderPaint = new Paint();
  21. private int mBorderColor = DEFAULT_BORDER_COLOR;
  22. private int mBorderWidth = DEFAULT_BORDER_WIDTH;
  23. private Bitmap mBitmap;
  24. private BitmapShader mBitmapShader;
  25. private int mBitmapWidth;
  26. private int mBitmapHeight;
  27. private float mDrawableRadius;
  28. private float mBorderRadius;
  29. private boolean mReady;
  30. private boolean mSetupPending;
  31. public CircleImageView(Context context) {
  32. super(context);
  33. }
  34. public CircleImageView(Context context, AttributeSet attrs) {
  35. this(context, attrs, 0);
  36. }
  37. public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
  38. super(context, attrs, defStyle);
  39. super.setScaleType(SCALE_TYPE);
  40. TypedArray a = context.obtainStyledAttributes(attrs,
  41. R.styleable.CircleImageView, defStyle, 0);
  42. mBorderWidth = a.getDimensionPixelSize(
  43. R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);
  44. mBorderColor = a.getColor(R.styleable.CircleImageView_border_color,
  45. DEFAULT_BORDER_COLOR);
  46. a.recycle();
  47. mReady = true;
  48. if (mSetupPending) {
  49. setup();
  50. mSetupPending = false;
  51. }
  52. }
  53. @Override
  54. public ScaleType getScaleType() {
  55. return SCALE_TYPE;
  56. }
  57. @Override
  58. public void setScaleType(ScaleType scaleType) {
  59. if (scaleType != SCALE_TYPE) {
  60. throw new IllegalArgumentException(String.format(
  61. "ScaleType %s not supported.", scaleType));
  62. }
  63. }
  64. @Override
  65. protected void onDraw(Canvas canvas) {
  66. if (getDrawable() == null) {
  67. return;
  68. }
  69. canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius,
  70. mBitmapPaint);
  71. if (mBorderWidth != 0) {
  72. canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius,
  73. mBorderPaint);
  74. }
  75. }
  76. @Override
  77. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  78. super.onSizeChanged(w, h, oldw, oldh);
  79. setup();
  80. }
  81. public int getBorderColor() {
  82. return mBorderColor;
  83. }
  84. public void setBorderColor(int borderColor) {
  85. if (borderColor == mBorderColor) {
  86. return;
  87. }
  88. mBorderColor = borderColor;
  89. mBorderPaint.setColor(mBorderColor);
  90. invalidate();
  91. }
  92. public int getBorderWidth() {
  93. return mBorderWidth;
  94. }
  95. public void setBorderWidth(int borderWidth) {
  96. if (borderWidth == mBorderWidth) {
  97. return;
  98. }
  99. mBorderWidth = borderWidth;
  100. setup();
  101. }
  102. @Override
  103. public void setImageBitmap(Bitmap bm) {
  104. super.setImageBitmap(bm);
  105. mBitmap = bm;
  106. setup();
  107. }
  108. @Override
  109. public void setImageDrawable(Drawable drawable) {
  110. super.setImageDrawable(drawable);
  111. mBitmap = getBitmapFromDrawable(drawable);
  112. setup();
  113. }
  114. @Override
  115. public void setImageResource(int resId) {
  116. super.setImageResource(resId);
  117. mBitmap = getBitmapFromDrawable(getDrawable());
  118. setup();
  119. }
  120. private Bitmap getBitmapFromDrawable(Drawable drawable) {
  121. if (drawable == null) {
  122. return null;
  123. }
  124. if (drawable instanceof BitmapDrawable) {
  125. return ((BitmapDrawable) drawable).getBitmap();
  126. }
  127. try {
  128. Bitmap bitmap;
  129. if (drawable instanceof ColorDrawable) {
  130. bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION,
  131. COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
  132. } else {
  133. bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
  134. drawable.getIntrinsicHeight(), BITMAP_CONFIG);
  135. }
  136. Canvas canvas = new Canvas(bitmap);
  137. drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
  138. drawable.draw(canvas);
  139. return bitmap;
  140. } catch (OutOfMemoryError e) {
  141. return null;
  142. }
  143. }
  144. private void setup() {
  145. if (!mReady) {
  146. mSetupPending = true;
  147. return;
  148. }
  149. if (mBitmap == null) {
  150. return;
  151. }
  152. mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
  153. mBitmapPaint.setAntiAlias(true);
  154. mBitmapPaint.setShader(mBitmapShader);
  155. mBorderPaint.setStyle(Paint.Style.STROKE);
  156. mBorderPaint.setAntiAlias(true);
  157. mBorderPaint.setColor(mBorderColor);
  158. mBorderPaint.setStrokeWidth(mBorderWidth);
  159. mBitmapHeight = mBitmap.getHeight();
  160. mBitmapWidth = mBitmap.getWidth();
  161. mBorderRect.set(0, 0, getWidth(), getHeight());
  162. mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2,
  163. (mBorderRect.width() - mBorderWidth) / 2);
  164. mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width()
  165. - mBorderWidth, mBorderRect.height() - mBorderWidth);
  166. mDrawableRadius = Math.min(mDrawableRect.height() / 2,
  167. mDrawableRect.width() / 2);
  168. updateShaderMatrix();
  169. invalidate();
  170. }
  171. private void updateShaderMatrix() {
  172. float scale;
  173. float dx = 0;
  174. float dy = 0;
  175. mShaderMatrix.set(null);
  176. if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width()
  177. * mBitmapHeight) {
  178. scale = mDrawableRect.height() / (float) mBitmapHeight;
  179. dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
  180. } else {
  181. scale = mDrawableRect.width() / (float) mBitmapWidth;
  182. dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
  183. }
  184. mShaderMatrix.setScale(scale, scale);
  185. mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth,
  186. (int) (dy + 0.5f) + mBorderWidth);
  187. mBitmapShader.setLocalMatrix(mShaderMatrix);
  188. }
  189. }

        自定义控件的attrs文件。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <!--自定义RadioButton,增加了控制图片的功能,不要在themes文件中也加上,否则会报错-->
  4. <declare-styleable name="DrawableRadioButton">
  5. <attr name="drawableSize" format="dimension"/>
  6. <attr name="drawableTop" format="reference"/>
  7. <attr name="drawableLeft" format="reference"/>
  8. <attr name="drawableRight" format="reference"/>
  9. <attr name="drawableBottom" format="reference"/>
  10. </declare-styleable>
  11. <declare-styleable name="CircleImageView">
  12. <attr name="border_width" format="dimension"/>
  13. <attr name="border_color" format="color" />
  14. </declare-styleable>
  15. </resources>

3、效果

3.1、书架页面

3.2、书城页面

3.3、我的页面

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/130657
推荐阅读
相关标签
  

闽ICP备14008679号