使用XML实现悬浮的添加按钮
- 不过于依赖过高版本
- 尽量简单易用
1,使用自定义的ImageButton来实现。一个圆加上加号,可以用LayerDrawable
2,按下时,四周出现了半透明的灰色边框。看起来本身背景的颜色也变深了,可以考虑属性动画或者selector(也可以自定义StateListDrawable),或者直接在Ondraw中绘制即可。
3,如何保证其在整个页面上方,并且不影响其他控件。
首先想到的就是FrameLayout
开动
先来把按钮做出来,效果是一个圆,一个加号。GradientDrawable来做圆,PNG的加号,然后通过LayerDrawable组合。
对于GradientDrawable 的使用可以参考Android 文档的Drawable Resources章节,添加
http://wiki.eoeandroid.com/Drawable
节选如下
Shape Drawable
这是一个定义在XML中的通用形状。
文件位置:
res/drawable/filename.xml
文件名作为资源ID。
编译后的资源数据类型:
指向一个渐变Drawable的资源指针。
资源引用:
Java: R.drawable.filename
XML: @[package:]drawable/filename
语法:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape=["rectangle" | "oval" | "line" | "ring"] >
<corners android:radius="integer" android:topLeftRadius="integer" android:topRightRadius="integer" android:bottomLeftRadius="integer" android:bottomRightRadius="integer" />
<gradient android:angle="integer" android:centerX="integer" android:centerY="integer" android:centerColor="integer" android:endColor="color" android:gradientRadius="integer" android:startColor="color" android:type=["linear" | "radial" | "sweep"] android:useLevel=["true" | "false"] />
<padding android:left="integer" android:top="integer" android:right="integer" android:bottom="integer" />
<size android:width="integer" android:height="integer" />
<solid android:color="color" />
<stroke android:width="integer" android:color="color" android:dashWidth="integer" android:dashGap="integer" />
</shape>
元素:
形状drawable,必须是根元素。
属性:
xmlns:android
字符型,必要的,定义XML的命名空间,必须是”http://schemas.android.com/apk/res/android“。
android:shape
关键字,定义形状的类型,取值是:
取值 | 描述 |
---|---|
“rectangle” | 填充包含的视图的矩形,是默认形状。 |
“oval” | 椭圆形,适合包含的视图的尺寸。 |
“line” | 划分包含的视图的水平线,这个形状要求元素来定义线的宽度。 |
“ring” | 环形。 |
如下属性只有当android:shape=”ring”时才使用。
android:innerRadius
尺寸,内环半径(中间的孔),作为一个尺寸值或尺寸资源。
android:thickness
尺寸,环的厚度,作为一个尺寸值或尺寸资源。
android:thicknessRatio
浮点型,环的厚度比上环的宽度,例如,如果android:thicknessRatio="2",厚度等于环的宽度的1/2,此值被android:innerRadius重写,默认为3.
android:useLevel
布尔型,为"true"时,用于LevelListDrawable,正常情况设为"false",或者形状不出现。
为形状创建圆角,只有当形状为矩形时才应用。
属性:
android:radius
尺寸数,所有的角的半径,作为一个尺寸值或尺寸资源,对于每个角会重写如下的属性:
android:topLeftRadius
尺寸数,左上角的半径,作为一个尺寸度值或尺寸资源。
android:topRightRadius
尺寸数,右上角的半径,作为一个尺寸度值或尺寸资源。
android:bottomLeftRadius
尺寸数,左下角的半径,作为一个尺寸值或尺寸度资源。
android:bottomRightRadius
尺寸数,右下角的半径,作为一个尺寸值或尺寸度资源。
注意:每个角的角半径必须大于1,不然没有圆角。如果想指定所有的角都不是圆角,使用android:radius 来设定默认的角半径大于1,然后重写每个角,并指定每个角的半径值为所需要的值,如果不需要圆角,值为0(0dp)。
为形状指定渐变颜色。
属性:
android:angle
整形,渐变的角度,度数,0度为从左到右,90度是从底到上,必须是45度的倍数,默认为0.
android:centerX
浮点型,距离渐变中心的X坐标的相对位置(0 - 1.0)。
android:centerY
浮点型,距离渐变中心的Y坐标的相对位置(0 - 1.0)。
android:centerColor
颜色,可选择开始到结束之间的颜色,作为一个十六进制值或颜色资源。
android:endColor
颜色,结束颜色,作为一个十六进制值或颜色资源。
android:gradientRadius
浮点型,渐变的半径,只有当android:type="radial"才使用
android:startColor
颜色,开始颜色,作为一个十六进制值或者颜色资源。
android:type
关键字,使用的渐变模式,有效值如下:
取值 | 描述 |
---|---|
linear | 线性渐变,默认选择 |
radial | 辐射渐变,开始颜色也是结束颜色 |
sweep | 卷曲线渐变 |
android:useLevel布尔型,为”true”时,作为一个 LevelListDrawable。
<padding>
填充以适用于视图元素(填充视图内容的位置而不是形状。
属性:
android:left
尺寸,左边填充,作为一个尺寸值或者尺寸资源。
android:top
尺寸,顶上填充,作为一个尺寸值或者尺寸资源。
android:right
尺寸,右边填充,作为一个尺寸值或者尺寸资源。
android:bottom
尺寸,底边填充,作为一个尺寸值或者尺寸资源。
形状的大小。
属性:
android:height
尺寸,形状的高,作为一个尺寸值或者尺寸资源。
android:width
尺寸,形状的宽,作为一个尺寸值或者尺寸资源。
注意:形状缩放大小以适应视图,与定义的尺寸相称,默认,当在一个图像视图使用形状时,可以限制缩放,通过设置 android:scaleType to "center"。
固定颜色填充形状。
属性:
android:color
颜色,用到形状上的颜色,作为一个十六进制值或颜色资源。
形状的笔触。
属性:
android:width
尺寸,线的宽度,作为一个尺寸值或尺寸资源。
android:color
颜色,线的颜色,作为一个十六进制值或者颜色资源。
android:dashGap
尺寸,虚线间隔,作为一个尺寸值或尺寸资源,只有当设置android:dashWidth才有效。
android:dashWidth
尺寸,每个虚线的大小,作为一个尺寸值或尺寸资源,只有当设置android:dashGap才有效。
例子:
XML文件存于res/drawable/gradient_Box.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient android:startColor="#FFFF0000" android:endColor="#80FF00FF" android:angle="45"/>
<padding android:left="7dp" android:top="7dp" android:right="7dp" android:bottom="7dp" />
<corners android:radius="8dp" />
</shape>
把此XML布局应用到一个视图的形状drawable:
<TextView android:background="@drawable/gradient_Box" android:layout_height="wrap_content" android:layout_width="wrap_content" />
应用程序代码获得形状drawable,应用到视图:
Resources res = getResources(); Drawable shape = res. getDrawable(R.drawable.gradient_Box); TextView tv = (TextView)findViewByID(R.id.textview); tv.setBackground(shape);
对于我们想要的一个圆形和加号,圆形用shape做,加号最初想也用shape做,然后组合为一个LayerDrawable,但是会有一个自动缩放的问题。
注意:
对于LayerDrawable默认情况下所有绘制项目缩放,以适应包含视图的大小。因此,放置图像在图层列表的不同位置,可能会增加View的大小和一些图像需要扩展到合适的大小。为了避免列表中的扩展项,在元素内使用元素,指定可绘制性和定义gravity为不会扩展的属性,诸如“居中”。例如,下面的定义了一个项,扩展到适应其容器View的大小:
<item android:drawable="@drawable/image" />
为避免扩展,如下的例子使用一个 元素,gravity属性为居中:
<item>
<bitmap android:src="@drawable/image" android:gravity="center" />
</item>
也没找到更好地办法阻止shape的放大,只能旋转PNG图片的Drawable来做加号
然后还需要按下和抬起时候的不同显示效果,可以使用StateListDrawable,在XML文件中则是selector 来定义。
代码:
(基本没有用java代码,全部用XML攒的)
layout
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" >
<ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="match_parent" >
</ListView>
<ImageButton android:id="@+id/imagebutton" android:layout_width="70dp" android:layout_height="70dp" android:layout_gravity="bottom|right" android:layout_marginBottom="20dp" android:layout_marginRight="20dp" android:background="@drawable/buttonselector" android:contentDescription="@string/hello_world" />
</FrameLayout>
buttonselector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:constantSize="true">
<item android:drawable="@drawable/pressbutton" android:state_pressed="true"></item>
<item android:drawable="@drawable/addbutton"></item>
</selector>
addbutton.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/bg" android:drawable="@drawable/circle">
</item>
<item android:id="@+id/add" android:drawable="@drawable/add2">
</item>
</layer-list>
pressbutton.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/bound" android:drawable="@drawable/circlebound">
</item>
<item android:id="@+id/add" android:drawable="@drawable/add2">
</item>
</layer-list>
circle.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="false" android:visible="true" >
<solid android:color="@color/blue" />
<stroke android:width="6dp" android:color="@color/transparent" />
<size android:height="40dp" android:width="40dp" />
</shape>
circlebound.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="false" android:visible="true" >
<solid android:color="@color/blue" />
<stroke android:width="3dp" android:color="@color/gray" />
<size android:height="45dp" android:width="45dp" />
</shape>
#
效果图(原谅我找的渣素材,电脑不能使用PS等软件):
后记: 写完发现其实把整个效果做成一个自定义的View是更好地,首先展开XML浪费很多时间。其次这么组合实际上比较复杂,并且Layer图像还有其自己的限制。 如果做成View。只需要在onDraw里面绘制即可。 并且可以增加比如加号旋转的属性,可以方便的做成属性动画,在后面需要让里面的加号旋转时直接创建一个属性动画即可。