zoukankan      html  css  js  c++  java
  • android悬浮按钮(Floating action button)的两种实现方法

    原文:

    http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1028/1857.html

    最近android中有很多新的设计规范被引入,最流行的莫过于被称作Promoted Actions的设计了,Promoted Actions是指一种操作按钮,它不是放在actionbar中,而是直接在可见的UI布局中(当然这里的UI指的是setContentView所管辖的范围)。因此它更容易在代码中被获取到(试想如果你要在actionbar中获取一个菜单按钮是不是很难?),Promoted Actions往往主要用于一个界面的主要操作,比如在email的邮件列表界面,promoted action可以用于接受一个新邮件。promoted action在外观上其实就是一个悬浮按钮,更常见的是漂浮在界面上的圆形按钮,一般我直接将promoted action称作悬浮按钮,英文名称Float Action Button 简称(FAB,不是FBI哈)。

    float action button是android l中的产物,但是我们也可以在更早的版本中实现。假设我这里有一个列表界面,我想使用floataction button代表添加新元素的功能,界面如下:

    http://a3ab771892fd198a96736e50.javacodegeeks.netdna-cdn.com/wp-content/uploads/2014/09/android_floating_action_button_14.png

    要实现float action button可以有多种方法,一种只适合android L,另外一种适合任意版本。

     

    用ImageButton实现

    这种方式其实是在ImageButton的属性中使用了android L才有的一些特性:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <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放到了布局的右下角,为了实现float action button应该具备的效果,需要考虑以下几个方面:

    ·Background

    ·Shadow

    ·Animation

    背景上我们使用ripple drawable来增强吸引力。注意上面的xml代码中我们将background设置成了@drawable/ripple ,ripple drawable的定义如下:

    1
    2
    3
    4
    5
    6
    7
    <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。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
        <item
            android:state_enabled="true"
            android:state_pressed="true">
            <objectAnimator
                android:duration="@android:integer/config_shortAnimTime"
                android:propertyName="translationZ"
                android:valueFrom="@dimen/start_z"
                android:valueTo="@dimen/end_z"
                android:valueType="floatType" />
        </item>
        <item>
            <objectAnimator
                android:duration="@android:integer/config_shortAnimTime"
                android:propertyName="translationZ"
                android:valueFrom="@dimen/end_z"
                android:valueTo="@dimen/start_z"
                android:valueType="floatType" />
        </item>
    </selector>

     

    使用自定义控件的方式实现悬浮按钮

    这种方式不依赖于android L,而是码代码。

    首先定义一个这样的类:

    1
    2
    3
    public class CustomFAB extends ImageButton {
    ...
    }

    然后是读取一些自定义的属性(假设你了解styleable的用法)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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文件中。

    1
    2
    3
    4
    5
    6
    7
    8
    <?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来实现不同状态下的背景

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    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中:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <RelativeLayout 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"
        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>

    项目的源码下载:github

  • 相关阅读:
    js压缩图片上传插件localResizeIMG
    valueOf函数详解
    垂直居中
    word-wrap,word-break,white-space
    理解bind函数
    float失效的情况
    塞码考试系统里的输入,到底是怎么回事
    理解position:relative
    border实现三角形的原理
    函数是对象,函数名是指针
  • 原文地址:https://www.cnblogs.com/mochaMM/p/5113597.html
Copyright © 2011-2022 走看看