1. 在android中怎样让按钮漂浮在图片上
android悬浮按钮(Floating action button)的两种实现方法
最近android中有很多新的设计规范被引入,最流行的莫过于被称作Promoted Actions的设计了,Promoted Actions是指一种操作按钮,它不是放在actionbar中,而是直接在可见的UI布局中(当然这里的UI指的是setContentView所管辖的范围)。因此它更容易在代码中被获取到(试想如果你要在actionbar中获取一个菜单按钮是不是很难?),Promoted Actions往往主要用于一个界面的主要操作,比如在email的邮件列表界面,promoted action可以用于接受一个新邮件。promoted action在外观上其实就是一个悬浮按钮,更常见的是漂浮在界面上的圆形按钮,一般我直接将promoted action称作悬浮按钮,英文名称Float Action Button简称(FAB,不是FBI哈)。
floatactionbutton是android l中的产物,但是我们也可以在更早的版本中实现。假设我这里有一个列表界面,我想使用floatactionbutton代表添加新元素的功能,界面如下:
要实现floatactionbutton可以有多种方法,一种只适合android L,另外一种适合任意版本。
用ImageButton实现
这种方式其实是在ImageButton的属性中使用了android L才有的一些特性:
<ImageButton
android:layout_width="56dp"
android:layout_height="56dp"
android:src="@drawable/plus"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
android:tint="@android:color/white"
android:id="@+id/fab"
android:elevation="1dp"
android:background="@drawable/ripple"
android:stateListAnimator="@anim/fab_anim"
/>
仔细一点,你会发现我们将这个ImageButton放到了布局的右下角,为了实现floatactionbutton应该具备的效果,需要考虑以下几个方面:
·Background
·Shadow
·Animation
背景上我们使用ripple drawable来增强吸引力。注意上面的xml代码中我们将background设置成了@drawable/ripple,ripple drawable的定义如下:
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight">
<item>
<shape android:shape="oval">
<solid android:color="?android:colorAccent" />
</shape>
</item>
</ripple>
既然是悬浮按钮,那就需要强调维度上面的感觉,当按钮被按下的时候,按钮的阴影需要扩大,并且这个过程是渐变的,我们使用属性动画去改变translatioz。
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_enabled="true"
android:state_pressed="true">
<objectAnimator
android:ration="@android:integer/config_shortAnimTime"
android:propertyName="translationZ"
android:valueFrom="@dimen/start_z"
android:valueTo="@dimen/end_z"
android:valueType="floatType" />
</item>
<item>
<objectAnimator
android:ration="@android:integer/config_shortAnimTime"
android:propertyName="translationZ"
android:valueFrom="@dimen/end_z"
android:valueTo="@dimen/start_z"
android:valueType="floatType" />
</item>
</selector>
使用自定义控件的方式实现悬浮按钮
这种方式不依赖于android L,而是码代码。
首先定义一个这样的类:
public class CustomFAB extends ImageButton {
...
}
然后是读取一些自定义的属性(假设你了解styleable的用法)
private void init(AttributeSet attrSet) {
Resources.Theme theme = ctx.getTheme();
TypedArray arr = theme.obtainStyledAttributes(attrSet, R.styleable.FAB, 0, 0);
try {
setBgColor(arr.getColor(R.styleable.FAB_bg_color, Color.BLUE));
setBgColorPressed(arr.getColor(R.styleable.FAB_bg_color_pressed, Color.GRAY));
StateListDrawable sld = new StateListDrawable();
sld.addState(new int[] {android.R.attr.state_pressed}, createButton(bgColorPressed));
sld.addState(new int[] {}, createButton(bgColor));
setBackground(sld);
}
catch(Throwable t) {}
finally {
arr.recycle();
}
}
在xml中我们需要加入如下代码,一般是在attr.xml文件中。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="FAB">
<!-- Background color -->
<attr name="bg_color" format="color|reference"/>
<attr name="bg_color_pressed" format="color|reference"/>
</declare-styleable>
</resources>
使用StateListDrawable来实现不同状态下的背景
private Drawable createButton(int color) {
OvalShape oShape = new OvalShape();
ShapeDrawable sd = new ShapeDrawable(oShape);
setWillNotDraw(false);
sd.getPaint().setColor(color);
OvalShape oShape1 = new OvalShape();
ShapeDrawable sd1 = new ShapeDrawable(oShape);
sd1.setShaderFactory(new ShapeDrawable.ShaderFactory() {
@Override
public Shader resize(int width, int height) {
LinearGradient lg = new LinearGradient(0,0,0, height,
new int[] {
Color.WHITE,
Color.GRAY,
Color.DKGRAY,
Color.BLACK
}, null, Shader.TileMode.REPEAT);
return lg;
}
});
LayerDrawable ld = new LayerDrawable(new Drawable[] { sd1, sd });
ld.setLayerInset(0, 5, 5, 0, 0);
ld.setLayerInset(1, 0, 0, 5, 5);
return ld;
}
最后将控件放xml中:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res/com.survivingwithandroid.fab"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MyActivity">
...
<com.survivingwithandroid.fab.CustomFAB
android:layout_width="56dp"
android:layout_height="56dp"
android:src="@android:drawable/ic_input_add"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
custom:bg_color="@color/light_blue"
android:tint="@android:color/white"
/>
</RelativeLayout>
2. android:elevation无效
在8.0版本,添加了z轴后并没有抬高?
android5.0 引入了Z轴的概念,于是就有着这种风格,也就是目前比较火的Material Design。
默认情况下,阴影是由background提供的,如果控件没有设置background,则需要加上
android:outlineProvider="bounds"
3. 01 CardView-使用
Material Design中有一种很个性的设计概念:卡片式设计(Cards),Cards拥有自己独特的UI特征,关于Cards的设计规范可以参考官网介绍: cards-usage Google在v7包中引进了一种全新的控件CardView,用来实现这种 Cards UI 的设计.
CardView继承自FrameLayout,它是一个带 圆角 背景和 阴影 的FrameLayout. CardView官方文档
一、简单使用
使用前添加依赖:
compile 'com.android.support:cardview-v7:25.3.1'
1、使用
CardView本质上属于FrameLayout,不同的是,它多了很多"特效"(圆角、阴影等).
可以看见,被CardView包裹的ImageView有明显的圆角和阴影,这就是CardView最重要的两条属性了.
app:cardCornerRadius=" " 圆角的半径,效果就是上面四个角的弧度
app:cardElevation=" " 阴影大小
2、关于Z轴的概念
Android5.0 引入了Z轴的概念,可以让组件呈现3D效果.看下面这幅图:
图中的FAB( FloatingActionButton )很明显是浮在界面上的,这就是Z轴的效果.
Z属性 可以通过elevation和translationZ进行修改 Z= elevation+translationZ
android:elevation=" " 设置该属性使控件有一个阴影,感觉该控件像是“浮”起来一样,达到3D效果
android:translationZ="" 设置该组件阴影在Z轴(垂直屏幕方向)上的位移
在 5.0之前 ,我们如果想给View添加阴影效果,以体现其层次感,通常的做法是给View设置一个带阴影的背景图片.在 5.0之后 ,我们只需要简单的修改View的 Z属性 ,就能让其具备阴影的层次感,不过要求版本至少5.0 Lollipop,也就是API21.
在 Android Design Support Library 和 support -v7 中一些组件已经封装好了Z属性,不需要5.0 就可以使用.
像 FloatingActionButton 就可以通过app:elevation=" "使用Z属性,CardView可以通过app:cardElevation=" " 来使用.关于Z轴的更多介绍,可以观看 官方:定义阴影与裁剪视图 .
二、CardView的常用属性
1、设置背景颜色
app:cardBackgroundColor=" "
2、设置padding
app:contentPadding=" "app:contentPaddingTop=" "app:contentPaddingBottom=" "app:contentPaddingLeft=" "app:contentPaddingRight=" "
Tips: 上面是CardView设置背景颜色和padding的方式,如果你直接通过android:padding=" " 和android:background=" "设置,是无效的.
3、设置Z轴的最大高度
app:cardMaxElevation=" "
4、点击之后的涟漪效果
android:clickable="true"android:foreground="?android:attr/selectableItemBackground"Tips:如果你给CardView设置了点击事件,就不需要设置android:clickable="true"了
如果你的CardView是可点击的,可以通过foreground属性使用系统定义好的RippleDrawable: selectableItemBackground ,从而达到在5.0及以上版本系统中实现点击时的涟漪效果(Ripple),如图:
这个涟漪效果在5.0以上版本中才能展示,在低版本上是一个普通的点击变暗的效果.
三、兼容性问题
1、边距问题
看下面两幅图:
在5.0之前的版本中设置了 app:cardElevation=" "后 CardView 会自动留出空间供阴影显示,而5.0之后的版本中没有预留空间. 官网也介绍了这种情况:
Before Lollipop, CardView adds padding to its content and draws shadows to that area. This padding amount is equal to maxCardElevation + (1 - cos45) * cornerRadius on the sides and maxCardElevation * 1.5 + (1 - cos45) * cornerRadius on top and bottom.
所以给CardView设置 Margin时需要兼容一下,否则在低版本上每个卡片之间的距离会特别大,浪费屏幕空间. 解决方法1: 在res/values/dimens中设置一个0dp的margin,这是为5.0之前版本使用的
<dimen name="cardview_margin">0dp</dimen>
在res/values-v21/dimens中设置一个适合的margin,为阴影预留空间,这是为5.0之后版本使用的
<dimen name="cardview_margin">12dp</dimen>
最后,给CardView设置外边距 android:layout_margin="@dimen/cardview_margin" ,这样就解决了低版本中边距过大浪费屏幕空间的问题了. 解决方法2: 直接给CardView设置该属性:
app:cardUseCompatPadding="true" 让CardView在不同系统中使用相同的padding值,为阴影预留空间
2、圆角问题
看下面两幅图:
在 >=5.0(Lollipop API 21)的版本 ,CardView会直接裁剪内容元素满足圆角的需求.在 <5.0(Lollipop API 21)的版本 ,CardView为了使内容元素不会覆盖CardView的圆角,会添加一个 padding ,这样一来,如果CardView设置了背景颜色,就很难看了. 解决方法: 给CardView设置该属性:
app:cardPreventCornerOverlap="false"这条属性的意思是:是否阻止圆角被覆盖,默认为true设为false后,padding效果就不存在了,同时圆角也被覆盖了该属性对5.X设备没什么影响.
四、小结
总的来说,如果在高版本中使用CardView还是很舒服的,很容易实现各种效果,低版本上兼容性还不是很好.
4. 怎么为android控件边缘添加阴影
为控件设置一个有阴影感的背景图片即可,可以使用shape
在自定义shape中增加一层或多层,并错开,即可显示阴影效果。为增加立体感,按钮按下的时候,只设置一层。我们可以通过top, bottom, right 和 left 四个参数来控制阴影的方向和大小
//自定义两种阴影效果
第一种
java"><?xmlversion="1.0"encoding="utf-8"?>
<selectorxmlns:android="http://schemas.android.com/apk/res/android">
<itemandroid:state_pressed="true">
<layer-list>
<itemandroid:left="4dp"android:top="4dp">
<shape>
<solidandroid:color="#ff58bb52"/>
<cornersandroid:radius="30dip"/>
</shape>
</item>
</layer-list>
</item>
<item>
<layer-list>
<!--第一层-->
<itemandroid:left="4dp"android:top="4dp">
<shape>
<solidandroid:color="#66000000"/>
<cornersandroid:radius="30dip"/>
<!--描边-->
<strokeandroid:width="1dp"android:color="#ffffffff"/>
</shape>
</item>
<!--第二层-->
<itemandroid:bottom="4dp"android:right="4dp">
<shape>
<solidandroid:color="#ff58bb52"/>
<cornersandroid:radius="30dip"/>
<!--描边-->
<strokeandroid:width="1dp"android:color="#ffffffff"/>
</shape>
</item>
</layer-list>
</item>
</selector>
第二种
<?xmlversion="1.0"encoding="utf-8"?>
<selectorxmlns:android="http://schemas.android.com/apk/res/android">
<!--点击之后-->
<itemandroid:state_pressed="true">
<layer-list>
<itemandroid:left="4dp"android:top="4dp">
<shape>
<solidandroid:color="#ff58bb52"/>
<cornersandroid:radius="3dp"/>
</shape>
</item>
</layer-list>
</item>
<!--正常状态-->
<item>
<layer-list>
<!--第一层-->
<itemandroid:left="2dp"android:top="2dp">
<shape>
<solidandroid:color="#66000000"/>
<cornersandroid:radius="3dp"/>
</shape>
</item>
<!--第二层-->
<itemandroid:bottom="4dp"android:right="4dp">
<shape>
<solidandroid:color="#ff58bb52"/>
<cornersandroid:radius="3dp"/>
</shape>
</item>
<!--第三层-->
<itemandroid:bottom="6dp"android:right="6dp">
<shape>
<solidandroid:color="#ffcccccc"/>
<cornersandroid:radius="3dp"/>
</shape>
</item>
</layer-list>
</item>
</selector>
设置后的效果图如下
5. android 低版本怎么使用 elevation 属性
ViewPagerTransforms 是一个自定义了各种翻转效果的开源库,其中的各种PageTransformer使用了view的很多属性设置方法如DepthPageTransformer中:
?
package com.ToxicBakery.viewpager.transforms;
import android.view.View;
public class DepthPageTransformer extends ABaseTransformer {
private static final float MIN_SCALE = 0.75f;
@Override
protected void onTransform(View view, float position) {
if (position <= 0f) {
view.setTranslationX(0f);
view.setScaleX(1f);
view.setScaleY(1f);
} else if (position <= 1f) {
final float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setAlpha(1 - position); ...
6. android 为什么使用viewoutlineprovider裁剪之后的view与原来一样
视图的高度(elevation),通过Z属性表现,通过他的阴影确定:z值更高的视图投影出更大的阴影。视图只在Z=0的平面上投影处阴影;他们不会投影阴影在其他放在下面的视图上面和高于z=0的平面。
有更高Z值的视图挡住Z值较低的视图。无论如何,Z值不会影响到View的大小。
高度也是有用的,当在执行一些动作的时候创建动画让组件升起。
为视图分配高度
一个View的Z值有两个组成部分,elevation(高度)和translation(平移).elevation是一个静态部分,translation 用于动画:
Z = elevation + translationZ
不同高度的视图的阴影
在布局文件中设置evelation 使用android:elevation,在代码中使用View.setElevation()方法。
设置一个视图的平移,使用View.setTranslationZ()方法。
新的方法ViewPropertyAnimator.z()和ViewPropertyAnimator.translationZ()可以让你更容易的变动视图的高度。更多的信息,看ViewPropertyAnimator的Api文档http://developer.android.com/reference/android/view/ViewPropertyAnimator.html。和属性动画的开发指南:http://developer.android.com/guide/topics/graphics/prop-animation.html。
你也可以使用StateListAnimator方式定义这些文件在xml文件中。特别适用于,状态改变时执行的动画,比如用户点击按钮。更多信息,请看动画视图状态改变,下次在动画一节讲。
Z值在测量上使用和X,Y值一样的单位。
自定义视图阴影和轮廓
视图的背景边界决定了阴影的默认形状。轮廓(Outlines)代表了图形对象的外形状,并确定了对触摸反馈区的波纹。
看这个视图,定义一个背景Drawable:
<TextView
android:id="@+id/myview"
...
android:elevation="2dp"
android:background="@drawable/myrect" />
背景是一个圆角矩形
<!-- res/drawable/myrect.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#42000000" />
<corners android:radius="5dp" />
</shape>
当这个背景drawable作为视图的轮廓,视图投射出圆角阴影。提供一个自定义的轮廓,可以覆盖默认视图阴影的形状。
在自己的代码中自定义一个轮廓:
1.继承ViewOutlineProvider类
2.重写getOutline()方法
3.在视图中设置轮廓,使用View.setOutlineProvider()方法
你可以创建椭圆和圆角矩形轮廓使用OutLine类中的方法。视图默认的outline provider会根据视图的背景来生成轮廓。可以设置视图的outline provider为null,来阻止投射阴影。
裁剪视图
裁剪视图功能,可以让你更容易的改变视图的形状。你可以裁剪视图为了和其他的设计元素保持一致,或者改变成形状响应用户的输入。你可以裁剪一个视图的轮廓使用View.setClipToOutLine()方法,或者android:clipToOutline属性。只有矩形,圆角矩形,圆圈的轮廓支持被裁剪,可以使用Outline.canClip()方法检测是否支持被裁剪。
裁剪视图到一个drawable的形状,设置drawable作为视图的背景(让视图显示在其上),并且调用View.setClipToOutline()方法。
裁剪视图是一个耗费的操作,裁剪视图时不要使用形状动画。达到这种效果,请使用Reveal Effect 动画
7. Android 浮窗按钮FloatActionButton
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<其他控件>
<android.support.design.widget.FloatingActionButton
android:id="@+id/pro_departmeng_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/pro_button"
android:onClick="onClick"
app:layout_anchor="@id/bc_pro_department"
app:layout_anchorGravity="right|top"
android:layout_marginRight="@dimen/size5"
app:rippleColor="@color/colorPrimary"
app:borderWidth="@dimen/size0"
android:elevation="@dimen/size5"
android:backgroundTint="@color/white"
app:fabSize="mini"/>
//初始化
@Bind(R.id.pro_departmeng_fab)
;
//监听事件
proDepartmengFab.setOnClickListener(newView.OnClickListener() {
@Override
public voidonClick(View view) {
Toast.makeText(getContext(),"test",Toast.LENGTH_LONG).show();
}
});
四、属性介绍
1、app:borderWidth=""------------------边框宽度,通常设置为0 ,用于解决Android 5.X设备上阴影无法正常显示的问题
2、app:backgroundTint=""---------------按钮的背景颜色,不设置,默认使用theme中colorAccent的颜色
3、app:rippleColor=""--------------------点击的边缘阴影颜色
4、app:elevation=""----------------------边缘阴影的宽度
5、app:pressedTranslationZ="16dp"-----点击按钮时,按钮边缘阴影的宽度,通常设置比elevation的数值大
8. android 低版本怎么使用 elevation 属性
低版本可以导入v7的兼容包,看看是否能有这个属性:
1. android:elevation 设置该组件“浮”起来的高度,to难过过设置该属性可以让该组件呈现3D效果。
2. android:translationZ 设置该组件在Z方向(垂直屏幕方向)上的位移。
对应的java方法:setElevation(float) setTranslationZ(float)
9. Android 5.0 elevation 设置阴影无效
elevation 设置阴影需要注意两点:
1、view需要设置背景
2、阴影是绘制在父控件上的,子控件和父控件之间要留空隙,用padding也不行
在开发过程中有过这样的布局:
我子Linearlayout是设置的圆角背景,结果这样的效果是:只有圆角的便便才有一丁点的阴影,原因是父布局设置的是padding,子控件是match_parent,空隙不足导致,将子布局改为margin,去掉父控件的padding就行了
10. Android开发,elevation无效
在properties->android->library->islibrary把islibrary勾上