|
/* |
|
* Copyright (C) 2014 uPhyca Inc. |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
package com.uphyca.widget; |
|
|
|
import android.animation.Animator; |
|
import android.animation.ObjectAnimator; |
|
import android.animation.StateListAnimator; |
|
import android.content.Context; |
|
import android.content.res.ColorStateList; |
|
import android.content.res.Resources; |
|
import android.graphics.Outline; |
|
import android.graphics.drawable.GradientDrawable; |
|
import android.graphics.drawable.RippleDrawable; |
|
import android.util.AttributeSet; |
|
import android.util.DisplayMetrics; |
|
import android.util.TypedValue; |
|
import android.widget.ImageButton; |
|
|
|
/** |
|
* FloatingActionButton のための UI パーツです。 |
|
* |
|
* 以下の様な感じで使います。 |
|
* <pre> |
|
* <com.uphyca.widget.FloatingActionButton |
|
* android:id="@+id/fab" |
|
* android:layout_width="56dp" |
|
* android:layout_height="56dp" |
|
* android:src="@drawable/ic_action_new"/> |
|
* </pre> |
|
*/ |
|
public class FloatingActionButton extends ImageButton { |
|
|
|
private static final int DEFAULT_ELEVATION_IN_DP = 2; |
|
private static final int DEFAULT_PRESSED_ELEVATION_IN_DP = 4; |
|
|
|
public FloatingActionButton(Context context) { |
|
super(context); |
|
init(context); |
|
} |
|
|
|
public FloatingActionButton(Context context, AttributeSet attrs) { |
|
super(context, attrs); |
|
init(context); |
|
} |
|
|
|
public FloatingActionButton(Context context, AttributeSet attrs, int defStyle) { |
|
super(context, attrs, defStyle); |
|
init(context); |
|
} |
|
|
|
public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { |
|
super(context, attrs, defStyleAttr, defStyleRes); |
|
init(context); |
|
} |
|
|
|
private void init(Context context) { |
|
final DisplayMetrics dm = context.getResources().getDisplayMetrics(); |
|
final float scale = dm.density; |
|
|
|
final int elevation = (int) (DEFAULT_ELEVATION_IN_DP * scale + .5f); |
|
final int pressedElevation = (int) (DEFAULT_PRESSED_ELEVATION_IN_DP * scale + .5f); |
|
final long duration = context.getResources().getInteger(android.R.integer.config_shortAnimTime); |
|
|
|
setElevation(elevation); |
|
initElevationAnimator(elevation, pressedElevation, duration); |
|
|
|
final int colorAccentValue; |
|
final int colorControlHighlightValue; |
|
if (isInEditMode()) { |
|
colorAccentValue = 0xff03a9f4; |
|
colorControlHighlightValue = 0x20444444; |
|
} else { |
|
final Resources.Theme theme = context.getTheme(); |
|
|
|
final TypedValue outValue = new TypedValue(); |
|
theme.resolveAttribute(android.R.attr.colorAccent, outValue, true); |
|
colorAccentValue = outValue.data; |
|
|
|
theme.resolveAttribute(android.R.attr.colorControlHighlight, outValue, true); |
|
colorControlHighlightValue = outValue.data; |
|
} |
|
|
|
final GradientDrawable ovalBackground = new GradientDrawable(); |
|
ovalBackground.setShape(GradientDrawable.OVAL); |
|
ovalBackground.setColor(colorAccentValue); |
|
|
|
final RippleDrawable rippleDrawable = new RippleDrawable(ovalBackground, ovalBackground); |
|
final ColorStateList rippleColors = new ColorStateList(new int[][]{EMPTY_STATE_SET}, new int[]{colorControlHighlightValue}); |
|
rippleDrawable.setColor(rippleColors); |
|
|
|
setBackground(rippleDrawable); |
|
} |
|
|
|
private void initElevationAnimator(float elevation, float pressedElevation, long duration) { |
|
final Animator onPressedAnimator = ObjectAnimator.ofFloat(this, "translationZ", |
|
elevation, pressedElevation); |
|
onPressedAnimator.setStartDelay(0L); |
|
onPressedAnimator.setDuration(duration); |
|
final Animator defaultAnimator = ObjectAnimator.ofFloat(this, "translationZ", |
|
pressedElevation, elevation); |
|
defaultAnimator.setStartDelay(0L); |
|
defaultAnimator.setDuration(duration); |
|
|
|
final StateListAnimator slm = new StateListAnimator(); |
|
slm.addState(PRESSED_ENABLED_STATE_SET, onPressedAnimator); |
|
slm.addState(EMPTY_STATE_SET, defaultAnimator); |
|
|
|
setStateListAnimator(slm); |
|
} |
|
|
|
@Override |
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) { |
|
super.onSizeChanged(w, h, oldw, oldh); |
|
|
|
final Outline outline = new Outline(); |
|
outline.setOval(0, 0, w, h); |
|
|
|
setOutline(outline); |
|
} |
|
} |