Android选中突出背景效果的底部导航栏功能

今天在群里看到一个底部导航选中突出效果像这样

就想着 这个应该怎么做呢,我记得类似咸鱼那种的是中间突出,不像这种 是选中哪个,哪个就突出

第一种方法

简单快捷,让UI帮忙切几张带突出背景的图片,

选中切换图片简单粗暴

在群里找小伙伴要了UI的切图一看给的6张图片一样大小,也不带突出背景

于是想着有没有第二种方法实现

百度了许久也许是我找的方法不对,也许是大家都没遇到这样的UI。

怎么办,自己想想,静下心来看UI效果,发现突出的地方有点像贝塞尔曲线

再细细分析一下,如果突出的是贝塞尔曲线那么如何画出一条直线,固定的位置突出呢

贝塞尔曲线是Path 里面的api,而Path 是可以连续画线的,

那么就好实现了,前面直接设置起点

mPath.moveTo(0, 0);//起始点

然后中间是直接的直接调用

mPath.lineTo(x,y);

需要突出就调用二阶贝塞尔曲线

mPath.quadTo(x1,y1,x2,y2);

果然可行,画出来效果是这样

不错 实现第一步了,但是仔细观察发现 人家下面是有白色背景的,突出的地方也要白色背景,怎么搞呢!

又去查了下Path 和Paint Api 发现 有一种方法可以实现这样的效果

mPaint.setStyle(Paint.Style.FILL_AND_STROKE);

画笔要设置成 这种风格的

mPath.lineTo(getWidth(), getHeight());
mPath.lineTo(0, getHeight());
mPath.close(); //封闭path路径

Path路径全部占满

然后就可以实现效果了

记得把画笔颜色设置成白色的哦

mPaint.setColor(Color.WHITE);

果然可行!

一顿布局出来的效果是这样的

好丑啊

不过已经迈出成功的第一步了,继续完善

首先这个突出的弧度好像跟UI不一样呀

又是一顿分析,发现突出的时候是有三个曲线组成的

那么就会有三个控制点

画的有点丑 凑合看

a b c 都是控制点
1-2 是第一段
2-3 是第二段
3-4 是第三段

三段对应三个控制点

所以我们要画四阶贝塞尔曲线

结果Path里面最多支持三阶。。。。。。。

没办法只能拆开成三个了

根据图可以算出 a b c 控制点和1 2 3 4点的位置

手机屏幕长度假设为w

现在底部是三个模块那么一个模块所占的距离 i=w/3

那么 1就是起始点

b是i的中心点

4是i点

Y方向的最高度为 -y(注意是负数哦)

假如按照三个贝塞尔曲线的长度都一样那么各个点的位置分别是

1(0,0)

2(i/2/2,y/2)
3(i-i/2/2,y/2)
4(i,0)
a(i/2/2/2,y/2/2/2)

b(i/2,y)

c(i-i/2/2/2,y/2/2/2)

那么我们把这些点套入贝塞尔曲线里面

//第一条贝塞尔曲线     a          2
mPath.quadTo(i / 2 / 2 / 2 , -(minHeight / 2 / 2 / 2), i / 2 / 2 , -(minHeight / 2));
//第二条贝塞尔曲线     b      3
mPath.quadTo(i / 2 + i , -minHeight, i - i / 2 / 2 + i , -(minHeight / 2));
//第三条贝塞尔曲线     c      4
mPath.quadTo(i - i / 2 / 2 / 2 , -(minHeight / 2 / 2 / 2), i + i * (count - 1), 0);

然后这是第一模块的,后面模块的计算就是加上几段i值

模块从1开始,现在是有3个模块数值就是 (1 2 3)

//第一条贝塞尔曲线     a          2
mPath.quadTo(i / 2 / 2 / 2 + i * (count - 1), -(minHeight / 2 / 2 / 2), i / 2 / 2 + i * (count - 1) + minHeight / 5, -(minHeight / 2));
//第二条贝塞尔曲线     b      3
mPath.quadTo(i / 2 + i * (count - 1), -minHeight, i - i / 2 / 2 + i * (count - 1) - minHeight / 5, -(minHeight / 2));
//第三条贝塞尔曲线     c      4
mPath.quadTo(i - i / 2 / 2 / 2 + i * (count - 1), -(minHeight / 2 / 2 / 2), i + i * (count - 1), 0);

这样就可以直接设置 count值 然后重新绘制就完成点击切换了

全部代码

package com.wavewave.mylibrary;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

/**
 * @author wavewave
 * @CreateDate: 2020/10/28 10:23 AM
 * @Description: 底部导航 选中突出View 背景
 * @Version: 1.0
 */
public class BottomOutNavigation extends View {
 private Paint mPaint;
 //起始点
 private int beginY = dip2px(0);
 //边距
 private int margin = dip2px(0);
 /**
  * 默认 突出最高点 Y
  */
 private int minHeight = dip2px(40);

 //第几个从0开始
 private int count = 1;
 /**
  * 默认3个 根据实际情况写
  */
 private int maxCount = 3;
 public static String TAG = "LineView";
 private int height;
 private int width;
 private Path mPath;

 public BottomOutNavigation(Context context) {
  this(context, null);
 }

 public BottomOutNavigation(Context context, @Nullable AttributeSet attrs) {
  this(context, attrs, 0);
 }

 public BottomOutNavigation(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  init();
 }

 private void init() {
  mPath = new Path();
  mPaint = new Paint();
//  mPaint.setStyle(Paint.Style.STROKE);
  mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
  mPaint.setColor(Color.WHITE);
  mPaint.setAntiAlias(true);//抗锯齿
  //2、通过Resources获取
  DisplayMetrics dm = getResources().getDisplayMetrics();
  height = dm.heightPixels;
  width = dm.widthPixels;
 }

 /**
  * 设置选择
  *
  * @param count
  */
 public void setCount(int count) {
  this.count = count;
  invalidate();
 }

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  int i = width / maxCount;//单个所占大小
  Log.d(TAG, "i:" + i);
  mPath.reset();
  mPath.moveTo(0, 0);//起始点
  mPath.lineTo(margin + i * (count - 1), 0);
//
  //第一条贝塞尔曲线     a          2
  mPath.quadTo(i / 2 / 2 / 2 + i * (count - 1), -(minHeight / 2 / 2 / 2), i / 2 / 2 + i * (count - 1) + minHeight / 5, -(minHeight / 2));
  //第二条贝塞尔曲线     b      3
  mPath.quadTo(i / 2 + i * (count - 1), -minHeight, i - i / 2 / 2 + i * (count - 1) - minHeight / 5, -(minHeight / 2));
  //第三条贝塞尔曲线     c      4
  mPath.quadTo(i - i / 2 / 2 / 2 + i * (count - 1), -(minHeight / 2 / 2 / 2), i + i * (count - 1), 0);

  mPath.lineTo(width, beginY);
  mPath.lineTo(getWidth(), getHeight());
  mPath.lineTo(0, getHeight());
  mPath.close(); //封闭path路径
  canvas.drawPath(mPath, mPaint);
 }
 /**
  * 根据屏幕的分辨率从 dp 的单位 转成为 px(像素)
  */
 public int dip2px(float dpValue) {
  final float scale = getResources().getDisplayMetrics().density;
  return (int) (dpValue * scale + 0.5f);
 }

}

这样就搞定了,中间突出那块 我按照平分后又减去了一点距离计算的。上gif图

代码我放到github上了,可以直接下载运行demo了解一下!

github代码链接

到此这篇关于Android选中突出背景效果的底部导航栏的文章就介绍到这了,更多相关android底部导航栏内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android 弹出Dialog时隐藏状态栏和底部导航栏的方法

    上代码 dialog.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); dialog.getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { @Override public void onSystemUi

  • Android用Scroller实现一个可向上滑动的底部导航栏

    静静等了5分钟竟不知道如何写我这第一篇文章.每次都想好好的学习学习,有时间多敲敲代码,写几篇自己的文章.今天终于开始实行了,还是有点小激动的.哈哈! 好了废话就不多收了.我今天想实现的一个功能就是一个可以上滑底部菜单栏.为什么我会想搞这么个东西呢, 还是源于一年前,我们app 有这么个需求,当时百度也好谷歌也好,都没有找到想要的效果,其实很简单的一个效果.但是当时我也是真的太菜了,所有有关自定义的控件真的是不会,看别人的代码还好,真要是自己写,一点头绪都没有.因为我试着写了,真的不行啊.当时觉得

  • 超简单的几行代码搞定Android底部导航栏功能

    超简单,几行代码搞定Android底部导航栏-–应项目需求以及小伙伴的留言,新加了两个方法: 设置底部导航栏背景图片 添加底部导航栏选项卡切换监听事件 底部导航栏的实现也不难,就是下边是几个Tab切换,上边一般是一个FrameLayout,然后FrameLayout中切换fragment. 网上有不少关于Android底部导航栏的文章,不过好像都只是关于下边Tab切的,没有实现Tab与fragment的联动,用的时候还要自己手写这部分代码,对我这个比较懒(据说,懒是程序员的一种美德_#)得程序员

  • 解决android 显示内容被底部导航栏遮挡的问题

    描述: 由于产品需求,要求含有EditText的界面全屏显示,最好的解决方式是使用AndroidBug5497Workaround.assistActivity(this) 的方式来解决,但是华为和魅族手机系统自带的有底部导航栏,会造成一些布局被遮挡. 解决方案:在values-21的style.xml中添加android:windowDrawsSystemBarBackgrounds"并将值设置为false,方式如下 在style引用的主题里面加入android:windowDrawsSyst

  • Android实现简单底部导航栏 Android仿微信滑动切换效果

    Android仿微信滑动切换最终实现效果: 大体思路: 1. 主要使用两个自定义View配合实现; 底部图标加文字为一个自定义view,底部导航栏为一个载体,根据需要来添加底部图标; 2. 底部导航栏的设置方法类似于TabLayout的关联,View需要创建关联方法,用来关联VIewPager; 3. 通过关联方法获取ViewPager实例后,根据ViewPager页面数创建底部导航栏的图标按钮; 代码实现: 1. 新建第一个自定义View, 图标 + 文字 的底部按钮; /** * 自定义控件

  • ANDROID BottomNavigationBar底部导航栏的实现示例

    第一种介绍的就是使用开源库,因为使用开源库最简单,也更加的符合我们的审美标准,同时BottomNavigationBar还是符合当前的Material Design标准的. 效果展示 依赖 compile'com.ashokvarma.android:bottom-navigation-bar:1.2.0' 布局文件 activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLa

  • Android选中突出背景效果的底部导航栏功能

    今天在群里看到一个底部导航选中突出效果像这样 就想着 这个应该怎么做呢,我记得类似咸鱼那种的是中间突出,不像这种 是选中哪个,哪个就突出 第一种方法 简单快捷,让UI帮忙切几张带突出背景的图片, 选中切换图片简单粗暴 在群里找小伙伴要了UI的切图一看给的6张图片一样大小,也不带突出背景 于是想着有没有第二种方法实现 百度了许久也许是我找的方法不对,也许是大家都没遇到这样的UI. 怎么办,自己想想,静下心来看UI效果,发现突出的地方有点像贝塞尔曲线 再细细分析一下,如果突出的是贝塞尔曲线那么如何画

  • Android实现底部导航栏功能

    本文实例为大家分享了Android实现底部导航栏功能的具体代码,供大家参考,具体内容如下 实验效果: (1)在drawable文件夹下新建tab_menu_bg.xml文件,具体代码如下: <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item

  • Android实现底部导航栏功能(选项卡)

    现在很多android的应用都采用底部导航栏的功能,这样可以使得用户在使用过程中随意切换不同的页面,现在我采用TabHost组件来自定义一个底部的导航栏的功能. 我们先看下该demo实例的框架图: 其中各个类的作用以及资源文件就不详细解释了,还有资源图片(在该Demo中借用了其它应用程序的资源图片)也不提供了,大家可以自行更换自己需要的资源图片.直接上各个布局文件或各个类的代码: 1. res/layout目录下的 maintabs.xml 源码: <?xml version="1.0&q

  • vue router仿天猫底部导航栏功能

    首先把天猫的导航贴出来,里面包括精选.品牌.会员.购物车.我五个导航及对应的图标. 分析: 1.图标的获取 进入阿里巴巴矢量图标库,网址  http://www.iconfont.cn. 点击官方图标库,选择天猫图标库,选中放入购物车. 点击添加至项目,点击创建新项目按钮,创建tianmao项目,点击确定. 此时会有查看在线链接和下载至本地两种方式,我选择第一种,因为后期如果要添加小图标的话,只需要重新生成在线链接,然后更新link即可 复制链接到index.html的link标签内,具体为 <

  • android中Fragment+RadioButton实现底部导航栏

    在App中经常看到这样的tab底部导航栏 那么这种效果是如何实现,实现的方式有很多种,最常见的就是使用Fragment+RadioButton去实现.下面我们来写一个例子 首先我们先在activity_mian.xml定义布局,整个布局的外面是线性布局,上面是帧布局切换不同的Fragment,底下是RadioGroup嵌套的是RadioButton.代码如下所示: <?xml version="1.0" encoding="utf-8"?> <Li

  • Android Fragment实现顶部、底部导航栏

    前言 无论是顶部还是底部导航栏,都是大多数APP的标配,网络上的相关实现教程也非常之多.最近回忆起以前写的小项目,发现对这块内容有些遗忘,不妨就再整理一遍代码逻辑,记录下来,方便日后查阅(指复制粘贴). 实现的方式有很多,本文采用以下方式实现: 底部导航栏:Fragment + BottomNavigationView 顶部导航栏:Fragment + ViewPager2 + TabLayout 底部导航栏 <布局文件> <?xml version="1.0" en

  • Android 中使用RadioGroup和Fragment实现底部导航栏的功能

    在一些购物商城中经常会遇到这类效果,效果图如下: 先看效果图 步骤一: 完成对主界面main.xml的创建: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/

  • 微信小程序实战之仿android fragment可滑动底部导航栏(4)

    底部3-5个选项的底部导航栏,目前在移动端上是主流布局之一,因此腾讯官方特地做了,可以通过设置,就可以做出了一个底部的导航栏. 相关教程:微信小程序教程系列之设置标题栏和导航栏(7) 但是通过设置的这个底部的导航栏,功能上比较固定,它必须要设置与它对应的一个页面,而且并不能滑动. 在业务上,有时候会比较限制,并不能完全满足所需. 又例如早前有人拿着UI稿问我,这种广告轮播图的样式,在小程序能不能实现呢? 我当时没有想了下,还不是很确定,因为小程序的轮播图的那几个小点点实在比较普通,样式单一. 因

  • Android实现带有指示器的自定义底部导航栏

    今天这篇文章,主要是给大家实现一个自定义的带有指示器的底部导航栏. 先看一下实现的效果吧. 这个自定义控件的使用要注意以下几个方面: 1.没有布局文件及资源文件,只需要一个java文件就可调用 2.可以非常灵活的使用,一句代码就可以添加到项目中 3.暂时只支持4.0以上版本,颜色值使用的是系统自带色值,如需在低版本使用,请自己替换颜色值 4.支持智能适配,可以根据底部按钮的数量,自动的调整布局 5.主内容区域,必须使用Fragment实现,通过附加到Viewpager上实现界面的左右滑动 下面给

随机推荐