前言
作为Material Design成员之一,旨在在手机、平板电脑、台式机和其它的平台提供一致、更广泛的外观和感觉。它有自身独特的动态效果,比如变形、弹出、位移等等,代表着当前页面上用户的特定操作。FloatingActionButton在用户界面起着不可替代的作用,看到这里是不是有一种跃跃欲试的感觉。
效果~
Part 1、FloatingActionButton常规应用
配置
dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') compile 'com.android.support:design:25.0.1'}代码<android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_margin="16dp" android:src="@android:drawable/ic_dialog_email" app:backgroundTint="@color/colorAccent" app:elevation="10dp" app:fabSize="normal" app:PRessedTranslationZ="12dp" android:clickable="true" app:rippleColor="#ff0" android:onClick="rotate"/>tips:1、app:fabSize="" : 设置Fab的大小,normal(56dp) mini(40dp)
2、app:backgroundTint="" : 设置Fab的背景
3、app:rippleColor="" : 设置Fab按下时的波纹效果(在5.0以上起作用)
4、app:elevation="" : 设置Fab正常状态下的海拔高度
5、app:pressedTranslationZ="" : 设置Fab按下的时候Z轴距离
6、在你想触发点击事件之前要设置clickable为true
效果~
从效果图可以看出5.0以上和5.0以下Fab的位置不一样,因为在5.0以下会默认为Fab设置边距所以在这里要使用两种尺寸
在5.0以下设置
android:layout_margin="0dp"在5.0以上设置android:layout_margin="16dp"效果~
问题解决了~
我们还可以为Fab设置动画效果
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) fab.getLayoutParams();// fab.animate().translationY(fab.getHeight()+layoutParams.bottomMargin).setInterpolator(new AccelerateInterpolator(3)); //fab.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3)); ObjectAnimator go = ObjectAnimator.ofFloat(fab,"translationY",0,fab.getHeight()+layoutParams.bottomMargin); go.setDuration(500); go.setInterpolator(new AccelerateInterpolator()); go.start(); go.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) fab.getLayoutParams(); ObjectAnimator back = ObjectAnimator.ofFloat(fab,"translationY",fab.getHeight()+layoutParams.bottomMargin,0); back.setDuration(500); back.setInterpolator(new DecelerateInterpolator()); back.start(); } });效果~
当然你也可以使用github上的库,如下所示
地址:https://github.com/makovkastar/FloatingActionButton
Part 2、FloatingActionButton的源码分析
* <p>Floating action buttons come in two sizes: the default and the mini. The size can be * controlled with the {@code fabSize} attribute.</p> * 悬浮的按钮有两个尺寸,默认和mini大小,这个尺寸和控制FabSize属性 * <p>As this class descends from {@link ImageView}, you can control the icon which is displayed * via {@link #setImageDrawable(Drawable)}.</p> * 这个类继承ImageView,你可以通过设置setImageDrawable来设置是否显示icon * <p>The background color of this view defaults to the your theme's {@code colorAccent}. If you * wish to change this at runtime then you can do so via * {@link #setBackgroundTintList(ColorStateList)}.</p> 这个View的默认背景颜色为你的主题colorAccent颜色,如果你希望改变这个可以通过setBackgroundTintList方法 */@CoordinatorLayout.DefaultBehavior(FloatingActionButton.Behavior.class)public class FloatingActionButton extends ImageButton {在来看一下构造方法
public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); ...... Drawable background = a.getDrawable(R.styleable.FloatingActionButton_android_background); mBackgroundTint = a.getColorStateList(R.styleable.FloatingActionButton_backgroundTint); mBackgroundTintMode = parseTintMode(a.getInt( R.styleable.FloatingActionButton_backgroundTintMode, -1), null); mRippleColor = a.getColor(R.styleable.FloatingActionButton_rippleColor, 0); mSize = a.getInt(R.styleable.FloatingActionButton_fabSize, SIZE_NORMAL); mBorderWidth = a.getDimensionPixelSize(R.styleable.FloatingActionButton_borderWidth, 0); final float elevation = a.getDimension(R.styleable.FloatingActionButton_elevation, 0f); final float pressedTranslationZ = a.getDimension( R.styleable.FloatingActionButton_pressedTranslationZ, 0f); a.recycle(); ...... final int sdk = Build.VERSION.SDK_INT; if (sdk >= 21) { mImpl = new FloatingActionButtonLollipop(this, delegate); } else if (sdk >= 12) { mImpl = new FloatingActionButtonHoneycombMr1(this, delegate); } else { mImpl = new FloatingActionButtonEclairMr1(this, delegate); } final int maxContentSize = (int) getResources().getDimension( R.dimen.design_fab_content_size); mContentPadding = (getSizeDimension() - maxContentSize) / 2; mImpl.setBackgroundDrawable(background, mBackgroundTint, mBackgroundTintMode, mRippleColor, mBorderWidth); mImpl.setElevation(elevation); mImpl.setPressedTranslationZ(pressedTranslationZ); setClickable(true); }从代码中不难看出,得到xml设置的属性,让FloatingActionButtonImpl实现随后查看测量方法@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int preferredSize = getSizeDimension(); final int w = resolveAdjustedSize(preferredSize, widthMeasureSpec); final int h = resolveAdjustedSize(preferredSize, heightMeasureSpec); // As we want to stay circular, we set both dimensions to be the // smallest resolved dimension final int d = Math.min(w, h); // We add the shadow's padding to the measured dimension setMeasuredDimension( d + mShadowPadding.left + mShadowPadding.right, d + mShadowPadding.top + mShadowPadding.bottom); }getSizeDimension()得到不同尺寸下的大小final int getSizeDimension() { switch (mSize) { case SIZE_MINI: return getResources().getDimensionPixelSize(R.dimen.design_fab_size_mini); case SIZE_NORMAL: default: return getResources().getDimensionPixelSize(R.dimen.design_fab_size_normal); } }resolveAdjustedSize()得到父控件测量之后的尺寸private static int resolveAdjustedSize(int desiredSize, int measureSpec) { int result = desiredSize;//将期望的大小赋值给result int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec);//得到实际的大小 switch (specMode) { case MeasureSpec.UNSPECIFIED://无穷大 result = desiredSize;//当mode为无穷大时,将最终值设置为期望值 break; case MeasureSpec.AT_MOST://不多于实际值 result = Math.min(desiredSize, specSize);//为了保证在内部区域画圆,得到两者的最小值 break; case MeasureSpec.EXACTLY://准确值 // No choice. Do what we are told. result = specSize; break; } return result; }上面的方法通过判断specMode来对result进行赋值
新闻热点
疑难解答