如上图,将两个按钮组合在一起,点击红色按钮将蓝色按钮隐藏或展开,中间用动画实现过渡,蓝色按钮上移或下移,红色按钮以一定规律旋转。实现思路不难,主要是熟悉一下自定义View的流程。
1.自定义属性。在values目录下新建文件,设置自定义View的属性。本例我们设置两个按钮的半径j就行了。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="comboButton">
<attr name="button_radius" format="dimension"/>
</declare-styleable>
</resources>
2.布局文件。从图可知这是组合控件,我们可以在LinearLayout中先放置按钮。
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:id="@+id/linear_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<android.support.design.widget.FloatingActionButton
android:id="@+id/floating_change_bt"
android:layout_margin="8dp"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@mipmap/icon2"
app:backgroundTint="#4f98e7"
app:backgroundTintMode="src_in"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/floating_bt"
android:layout_margin="8dp"
android:layout_marginTop="10dp"
android:layout_width="50dp"
android:layout_height="50dp"
app:backgroundTint="#dc5d48"
android:src="@mipmap/icon"
/>
</LinearLayout>
3.编写自定义View。新建comboButton类继承LinearLayout,注意类名要与自定义属性文件中declare-styleable的name相同,才能获取到自定义属性。
public class comboButton extends LinearLayout implements View.OnClickListener{
private FloatingActionButton button; //红色按钮
private FloatingActionButton changeButton; //蓝色按钮
private float buttonY; //红色按钮Y坐标
private float changeButtonY; //蓝色按钮Y坐标
private click mClick; // 点击实例
private int radius; //半径
public comboButton(Context context){
this(context,null,0);
}
public comboButton(Context context, AttributeSet attrs){
this(context, attrs,0);
}
public comboButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//获取自定义属性
TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.comboButton,defStyleAttr,0);
radius = array.getInteger(R.styleable.comboButton_button_radius,100);
array.recycle();
initView(context);
}
public void initView(Context context){
//引入布局
LayoutInflater.from(context).inflate(R.layout.combo_button, this, true);
button = findViewById(R.id.floating_bt);
changeButton = findViewById(R.id.floating_change_bt);
//设置半径
android.view.ViewGroup.LayoutParams lp = button.getLayoutParams();
lp.width = radius;
lp.height = radius;
lp = changeButton.getLayoutParams();
lp.width = radius;
lp.height = radius;
//设置点击
button.setOnClickListener(this);
changeButton.setOnClickListener(this);
//先将蓝色按钮设为不可见,不可点击
if(changeButton.getVisibility() == VISIBLE){
changeButton.setVisibility(INVISIBLE);
changeButton.setEnabled(false);
}
//获取两个按钮Y坐标,将蓝色按钮坐标改为红色坐标,达到与红色重叠效果
new Thread(){
@Override
public void run() {
try {
sleep(300);
}catch (InterruptedException e){
e.printStackTrace();
}
buttonY = button.getY();
changeButtonY = changeButton.getY();
changeButton.setY(buttonY);
}
}.start();
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.floating_bt:
//根据蓝色按钮状态响应点击事件
if(changeButton.getVisibility() == INVISIBLE){
//将蓝色变为可见,可点击
changeButton.setVisibility(VISIBLE);
changeButton.setEnabled(true);
//设置动画效果
ObjectAnimator objectAnimator =ObjectAnimator.ofFloat(changeButton,"translationY", 0 );
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(button,"rotation",0f, 45f);
AnimatorSet set = new AnimatorSet();
set.setDuration(1000);
set.play(objectAnimator).with(objectAnimator1);
set.start();
}else if(changeButton.getVisibility() == VISIBLE){
//设置动画效果
ObjectAnimator objectAnimator =ObjectAnimator.ofFloat(changeButton,"translationY",buttonY - changeButtonY);
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(button,"rotation",45f, 0f);
AnimatorSet set = new AnimatorSet();
set.setDuration(1000);
set.play(objectAnimator).with(objectAnimator1);
set.start();
//动画结束将蓝色按钮设为不可见,不可点击
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
changeButton.setVisibility(INVISIBLE);
changeButton.setEnabled(false);
}
});
}
break;
case R.id.floating_change_bt:
//蓝色按钮点击事件设置接口,外部调用
mClick.onButtonClick();
}
}
public void setClickEvent(click c){
mClick = c;
}
//蓝色按钮点击接口
interface click{
void onButtonClick();
}
}
由布局文件可知蓝色按钮一开始在红色上面,即展开状态。所以在初始化时我们先将蓝色按钮设为不可见,并将Y坐标设为与红色按钮相同,达到重叠效果(这里先将两个按钮Y坐标保存,以后还需要用到)。从上面代码可以看到我们先开个线程sleep一小段时间后才获取按钮的坐标。这是因为一开始就获取的话获取到的值为0.0。(可通过打印日志证明)。
当点击红色按钮时,根据蓝色按钮是否可见,即是否展开响应事件。展开收起通过设置属性动画实现过渡。蓝色按钮的点击事件具体逻辑通过设置接口回调,交给外部设置。
接着只要在布局中引用就可以了。(当然这个控件并不是那么完美)