当前位置:网站首页>ViewOverlay与ViewGroupOverlay
ViewOverlay与ViewGroupOverlay
2022-08-08 23:10:00 【jxq1994】
有关ViewOverlay的官方文档非常清晰,您应该阅读它。
它是什么?
ViewOverlay 是存在于API 18+(Android 4.3)内的类,它是位于View视图层顶部的一个附加层,在View所有内容绘制完成后被绘制。 ViewGroupOverlay 是ViewOverlay的子类,对应于ViewGroup,同样地,这个层在ViewGroup中所有内容(包括childView)绘制完毕后才会被绘制。这个层和我们的View拥有同样的尺寸,可看做浮在View上方的一个二维空间。
Overlay对象可通过 View.getOverlay() 或 ViewGroup.getOverlay() 方法获得,获得Overlay对象后,就可以通过add、clear和remove方法操作其中的元素,这也是Overlay仅有的几个方法。
要记住重叠的重要点:
- 两种覆盖类型:ViewOverlay(用于视图)和ViewGroupOverlay(用于ViewGroup)
- 两种检索视图叠加的方法:
View.getViewOverlay
/ViewGroup.getViewGroupOverlay
- 您可以添加/删除一个drawable 在ViewOverlay和ViewGroupOverlay
- 您可以在ViewGroupOverlay中添加/删除View
- 文档上说
An overlay [...] on top of a View [...] drawn after all other content in that view [...]
我们先看看View.getViewOverlay
/ View.getViewGroupOverlay
方法。
public ViewOverlay getOverlay() {
if (mOverlay == null) {
mOverlay = new ViewOverlay(mContext, this);
}
return mOverlay;
}
public ViewGroupOverlay getOverlay() {
if (mOverlay == null) {
mOverlay = new ViewGroupOverlay(mContext, this);
}
return (ViewGroupOverlay) mOverlay;
}
调用get方法时会创建ViewOverlay / ViewGroupOverlay。
ViewOverlay / ViewGroupOverlay如何工作? 请注意,ViewGroupOverlay继承自ViewOverlay,因此我们可以专注于ViewOverlay实现。
ViewOverlay实现基于OverlayViewGroup(ViewOverlay中的静态内部类)。OverlayViewGroup继承自ViewGroup并包含一个drawable列表 。正如你所看到的,没有任何方法来布置drawables或view,这就是你负责定位/调整它们的原因。
它怎么用?
带横幅的按钮(VIEWOVERLAY)
在这里,我们希望在按钮的右上角添加一些带有文字的横幅,如下所示。
主要困难是我们不希望按钮的行为被横幅(即点击,触摸等)改变。
基本的xml布局
这里我们有一个按钮的基本布局。
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:text="Click me even if I'm a pirate"
android:background="@drawable/badged"
android:layout_width="250dp"
android:layout_height="250dp"
android:textColor="#FFF"
android:fontFamily="sans-serif-condensed"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
自定义Drawable
为了获得更大的灵活性(更改横幅颜色,文本等),您必须实施自定义绘图。
class BannerDrawable extends Drawable {
private static final double SQRT_2 = Math.sqrt(2);
private final Rect mTextBounds;
private Paint mPaintFill;
private Paint mPaintText;
private String mMessage = "I'M A PIRATE BANNER";
private int mBannerWidth = 50;
private int mTextSize;
public BannerDrawable() {
initPaintFill();
initPaintText();
mTextBounds = new Rect();
}
private void initPaintFill() {
mPaintFill = new Paint(ANTI_ALIAS_FLAG);
mPaintFill.setStyle(Paint.Style.FILL);
mPaintFill.setColor(getResources().getColor(R.color.banner));
}
private void initPaintText() {
mPaintText = new Paint(ANTI_ALIAS_FLAG);
mPaintText.setStyle(Paint.Style.FILL);
mPaintText.setColor(Color.WHITE);
mPaintText.setTextSize(20);
mPaintText.setShadowLayer(4.0f, 2.0f, 2.0f, Color.BLACK);
}
@Override
public void draw(Canvas canvas) {
Rect bounds = getBounds();
if (bounds.isEmpty()) {
bounds = canvas.getClipBounds();
}
float width = bounds.width();
adaptTextSize((int) (width * 0.9), (int) (mBannerWidth * 0.9));
float bannerHyp = (float) (mBannerWidth * SQRT_2);
canvas.translate(0, bounds.centerY() - mBannerWidth);
canvas.rotate(45, bounds.centerX(), bounds.centerY() - mBannerWidth);
canvas.drawRect(bounds.left - bannerHyp, bounds.top, bounds.right + bannerHyp, bounds.top + mBannerWidth, mPaintFill);
canvas.drawText(mMessage, bounds.centerX() - mTextBounds.centerX(), mBannerWidth / 2 + mTextBounds.height() / 2, mPaintText);
}
private void adaptTextSize(float width, int height) {
if (mTextSize > 0) {
mPaintText.setTextSize(mTextSize);
return;
}
int textSize = 10;
int textHeight;
int textWidth;
boolean stop = false;
while (!stop) {
mTextSize = textSize++;
mPaintText.setTextSize(mTextSize);
mPaintText.getTextBounds(mMessage, 0, mMessage.length(), mTextBounds);
textHeight = mTextBounds.height();
textWidth = mTextBounds.width();
stop = textHeight >= height || textWidth >= width;
}
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(ColorFilter cf) {
}
@Override
public int getOpacity() {
return PixelFormat.OPAQUE;
}
}
最后,使用ViewOverlay
最后一步很简单。它包括调整和定位BannerDrawable,并在按钮已完全布局时将其添加到按钮的ViewOverlay。
请注意,可绘制边界是按钮的右上方。
final View button = findViewById(R.id.button);
final ViewOverlay overlay = button.getOverlay();
final BannerDrawable bannerDrawable = new BannerDrawable();
button.post(new Runnable() {
@Override
public void run() {
//top right square
bannerDrawable.setBounds(button.getWidth() / 2, 0, button.getWidth(), button.getHeight() / 2);
overlay.add(bannerDrawable);
}
});
边栏推荐
- 如何使用 Eolink 实现 API 文档自动生成
- Tp5 in cache cache, storage cell phone text message authentication code
- (2022杭电多校五)1010-Bragging Dice (思维)
- 面试常问问题之网络整体传输过程
- Pyhton面对对象
- JSDay1-合并两个有序数组
- (2022牛客多校五)G-KFC Crazy Thursday(二分+哈希/Manacher)
- PHP regular to img SRC to add the domain name
- -Wl,--start-group ... -Wl,--end-group 用于解决几个库的循环依赖关系
- 【YOLOv5】6.0环境搭建(不定时更新)
猜你喜欢
随机推荐
sess.restore() 和 tf.import_meta_graph() 在使用时的一些关联
想要精准营销,从学习搭建一套对的标签体系开始丨DTVision分析洞察篇
最详树莓派4B装机流程及ifconfig不到wlan0的解决办法
flutter 书写json解析类
虚拟化类型(配图)
LeetCode:正则表达式匹配
ABP中的数据过滤器
Button Wizard for ts API usage
Introduction to Qt (5) - file operation, hotkey and mouse reading (implementation of txt window)
2022牛客多校六 B-Eezie and Pie (dfs)
(Codeforce 757)E. Bash Plays with Functions(积性函数)
flutter 基本类写法
用工具实现 Mock API 的整个流程
Kubernetes 资源核心原理
Tp5 in cache cache, storage cell phone text message authentication code
2022杭电多校六 1007-Shinobu loves trip(同余方程)
meta learning
CTF Attack and Defense World
【Tensorflow2】tensorflow1.x-tensorflow2.x一些接口的转变
php 将时间戳转化为 刚刚、几分钟前、几小时前、几天前 格式