Android实现三角形气泡效果方式汇总
作者:龙旋 发布时间:2021-12-20 06:21:51
标签:Android,三角形气泡
在开发过程中,我们可能会经常遇到这样的需求样式:
这张图是截取京东消息通知的弹出框,我们可以看到右上方有个三角形的气泡效果,这只是其中一种,三角形的方向还可以是上、下、左、右。
通过截图可以发现,气泡由正三角形和圆角长方形组成,于是可以通过组合来形成三角形气泡的效果,下面我们通过三种方式进行实现。
实现方式:
1、通过.9图进行实现;
2、通过shape方式实现;
3、通过自定义view的方式实现;
实现逻辑:
1、通过.9图进行实现
这种方式就不用说了吧,找你们UI小姐姐切一个.9图,使用即可,不过这种方式的图片需要占一定体积哦。
2、通过shape方式实现
正三角形
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate
android:fromDegrees="45"
android:pivotX="-40%"
android:pivotY="80%">
<shape android:shape="rectangle">
<size
android:width="15dp"
android:height="15dp" />
<solid android:color="#ffffff" />
</shape>
</rotate>
</item>
</layer-list>
倒三角形
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate
android:fromDegrees="45"
android:pivotX="135%"
android:pivotY="15%">
<shape android:shape="rectangle">
<size
android:width="15dp"
android:height="15dp" />
<solid android:color="#ffffff" />
</shape>
</rotate>
</item>
</layer-list>
左三角形
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate
android:fromDegrees="-45"
android:pivotX="85%"
android:pivotY="-35%">>
<shape android:shape="rectangle">
<size
android:width="15dp"
android:height="15dp" />
<solid android:color="#ffffff" />
</shape>
</rotate>
</item>
</layer-list>
右三角形
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate
android:fromDegrees="-45"
android:pivotX="15%"
android:pivotY="135%">>
<shape android:shape="rectangle">
<size
android:width="15dp"
android:height="15dp" />
<solid android:color="#ffffff" />
</shape>
</rotate>
</item>
</layer-list>
上面就是通过shape方式实现各个方向的代码,这种方式缺点比较明显,如果要变化不同的角的位置需要再写不同的布局。
3、通过自定义view的方式实现
由于是比较简单这里就不讲解每个怎么搞了,可以复制过去直接用
添加自定义属性
<declare-styleable name="TriangleView">
<attr name="trv_color" format="color" />
<attr name="trv_direction">
<enum name="top" value="0" />
<enum name="bottom" value="1" />
<enum name="right" value="2" />
<enum name="left" value="3" />
</attr>
</declare-styleable>
自定义代码文件
public class TriangleView extends View {
private static final int TOP = 0;
private static final int BOTTOM = 1;
private static final int RIGHT = 2;
private static final int LEFT = 3;
private static final int DEFUALT_WIDTH = 10;
private static final int DEFUALT_HEIGHT = 6;
private static final int DEFUALT_COLOR = R.color.FFF;
private Paint mPaint;
private int mColor;
private int mWidth;
private int mHeight;
private int mDirection;
private Path mPath;
public TriangleView(final Context context) {
this(context, null);
}
public TriangleView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public TriangleView(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TriangleView, 0, 0);
mColor = typedArray.getColor(R.styleable.TriangleView_trv_color, ContextCompat.getColor(getContext(), DEFUALT_COLOR));
mDirection = typedArray.getInt(R.styleable.TriangleView_trv_direction, mDirection);
typedArray.recycle();
mPaint.setColor(mColor);
}
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
mPath = new Path();
mDirection = TOP;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = MeasureSpec.getSize(widthMeasureSpec);
mHeight = MeasureSpec.getSize(heightMeasureSpec);
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (mWidth == 0 || widthMode != MeasureSpec.EXACTLY) {
mWidth = (int) PixelUtil.dp2px(DEFUALT_WIDTH);
}
if (mHeight == 0 || heightMode != MeasureSpec.EXACTLY) {
mHeight = (int) PixelUtil.dp2px(DEFUALT_HEIGHT);
}
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
switch (mDirection) {
case TOP:
mPath.moveTo(0, mHeight);
mPath.lineTo(mWidth, mHeight);
mPath.lineTo(mWidth / 2, 0);
break;
case BOTTOM:
mPath.moveTo(0, 0);
mPath.lineTo(mWidth / 2, mHeight);
mPath.lineTo(mWidth, 0);
break;
case RIGHT:
mPath.moveTo(0, 0);
mPath.lineTo(0, mHeight);
mPath.lineTo(mWidth, mHeight / 2);
break;
case LEFT:
mPath.moveTo(0, mHeight / 2);
mPath.lineTo(mWidth, mHeight);
mPath.lineTo(mWidth, 0);
break;
default:
break;
}
mPath.close();
canvas.drawPath(mPath, mPaint);
}
}
布局文件添加
<com.sjl.keeplive.triange.TriangleView
android:layout_width="10dp"
android:layout_height="6dp"
app:trv_color="@color/FFF"
app:trv_direction="top" />
通过自定义的方式可以搞定四个方向,而且在代码中也可以使用,动态添加,动态改变颜色,还是比较好的方式。
来源:https://segmentfault.com/a/1190000039376986


猜你喜欢
- 今天把Android Studio 2.3 更新为了3.0 遇到一个蛋疼的问题如图:格式化完代码后发现不会自动换行了,看着真心不爽。后来发现
- Object(四大方法):文章干货满满,耐性看完~~何为Object?首先先来看看官方对Object的介绍:在这里附上Java官方的查阅工具
- /// <summary> /// 安装的excel的版本,0为没有安装,大于1说明安装了多个. /// </summar
- 前言前面文章我们介绍了Broker是如何将消息全量存储到CommitLog文件中,并异步生成dispatchRequest任务更新Consu
- 本文为大家分享了Android Toast全屏显示的具体代码,供大家参考,具体内容如下废话不说,直接上代码:private void toa
- 我们在使用C# 语言的Assembly.Load 来加载托管程序集并使用反射功能时,一般需要先通过Assembly.Load()
- 前言1、下面是一个效果展示;2、先抱怨一下,在博客上面的抄袭真的非常严重,为了实现一个图片滑动验证,我搜索了挺久的资料,不过内容翻来覆去就是
- 1. 需求描述有这样一个需求,用ViewPager实现图片滑动,其下方有一个tab,每一个tab的标签对应一组图片,在ViewPager中的
- 为什么Android要申请权限简单说下在Android6.0及6.0以上一些google认为涉及“危险和用户隐私”的一些权限不仅要做清单文件
- mybatis官网中文文档:https://mybatis.org/mybatis-3/zh/sqlmap-xml.htmlmybatis-
- 语法糖(Syntactic sugar)是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中
- 什么是文件上传?文件上传就是把用户的信息保存起来。为什么需要文件上传?在用户注册的时候,可能需要用户提交照片。那么这张照片就应该要进行保存。
- 本文实例讲述了Java设计模式之 * 模式。分享给大家供大家参考,具体如下: * 模式有三个要素——事件源、事件对象、 * 。事件源:顾名思
- 不依赖任何外界包,maven如何生成可以执行的jar?pom中不包含任何引用的情况下,只需要在pom中添加 maven-jar-plugin
- ScrollConfiguration( behavior: NoScrollBehaviorWidget(),
- 具体代码如下所示:public class MainActivity extends AppCompatActivity { p
- 本文实例讲述了Android软键盘弹出时的界面控制方法。分享给大家供大家参考,具体如下:有时候androidactivity弹出软键盘后布局
- DozerDozer是一种Java Bean到Java Bean的映射器,递归地将数据从一个对象复制到另一个对象,它是一个强大的,通用的,灵
- 概念逃逸分析一种数据分析算法,基于此算法可以有效减少 Java 对象在堆内存中的分配。 Hotspot 虚拟机的编译器能够分析出一个新对象的
- 重载1.构造器的重载因为构造器的名字必须与类名相同,所以同一个类的所有构造器名肯定相同,构成重载;为了让系统能区分不同的构造器,多个构造器的