一、弹出菜单
制作一个可以弹出的菜单,具体直接看效果吧~
具体实现:
1,在XML文件里面添加图片按钮
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/id_d"
style="@style/ManuBtnStyle"
android:src="@drawable/d"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/id_c"
style="@style/ManuBtnStyle"
android:src="@drawable/c"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/id_b"
style="@style/ManuBtnStyle"
android:src="@drawable/b"
/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/id_a"
android:background="@null"
style="@style/ManuBtnStyle"
android:src="@drawable/a"/>
</RelativeLayout>
2,为按钮设置样式,在values文件中
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="ManuBtnStyle">
<item name="android:background">@null</item>
<item name="android:layout_alignParentBottom">true</item>
<item name="android:layout_centerHorizontal">true</item>
</style>
</resources>
3,添加动画
(1),定义数组保存所有的动画按钮的资源ID
private int[] resld = {R.id.id_b,R.id.id_c,R.id.id_d};
(2),获取菜单按钮的状态,并为菜单按钮添加点击事件,isOpen记录按钮菜单的是否是打开状态
private void initView(){
//给菜单添加点击事件
ImageButton menu = findViewById(R.id.id_a);
menu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//遍历数组,取出每一个按钮
for(int i = 0;i < resld.length;i++){
//判断是打开 还是关闭
if(isOpen == true){
//之前是打开 ,现在需要关闭
close(i);
}else{
//之间是关闭,现在需要打开
open(i);
}
}
isOpen = !isOpen;
}
});
}
(3),定义方法封装菜单的open和close动画
public void close(int i){
animate(i,true);
}
public void open(int i){
animate(i,false);
}
(4),实现动画,使用AnimationSet管理多个动画
public void animate(int i,boolean state){
//计算菜单平分之后的夹角
double angle = (Math.PI/(resld.length+1));
//获取id对应的控件
ImageButton imageButton = findViewById(resld[i]);
//计算当前控制对应控件的角度
double mAngle = (i+1) * angle;
//计算x距离
float x = (float)(Math.cos(mAngle) * 400);
//计算y距离
float y = (float)(Math.sin(mAngle) * 400);
float startx;
float tox;
float starty;
float toy;
Interpolator interpolator;
if(state == true){
startx = 0;
starty = 0;
tox = x;
toy = -y;
interpolator = new BounceInterpolator();
}else{
startx = x;
starty = -y;
tox = 0;
toy = 0;
interpolator = new AnticipateInterpolator();
}
//移动的动画
TranslateAnimation translateAnimation = new TranslateAnimation(startx,tox,starty,toy);
translateAnimation.setDuration(500);
translateAnimation.setInterpolator(interpolator);
//旋转的动画
RotateAnimation rotateAnimation = new RotateAnimation(0,360*3, Animation.RELATIVE_TO_SELF,
0.5f,Animation.RELATIVE_TO_SELF,0.5f);
rotateAnimation.setDuration(500);
//创建一个Animation集合 包裹多个动画
AnimationSet set = new AnimationSet(false);
set.setFillAfter(true); //保持状态
set.addAnimation(rotateAnimation);
set.addAnimation(translateAnimation);
//开始动画
imageButton.startAnimation(set);
}
二、多级菜单
先展示效果:
具体实现:
1,在XML文件里面添加每层菜单的布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"/>
<!-- 一级菜单-->
<RelativeLayout
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@drawable/level1"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true">
<ImageButton
android:id="@+id/ib_home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_home"
android:background="@null"
android:layout_centerInParent="true"/>
</RelativeLayout>
<!-- 二级菜单-->
<RelativeLayout
android:id="@+id/rl_level2"
android:layout_width="200dp"
android:layout_height="100dp"
android:background="@drawable/level2"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
>
<ImageButton
android:id="@+id/ib_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_menu"
android:background="@null"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_search"
android:background="@null"
android:layout_alignParentBottom="true"
android:layout_marginLeft="150dp"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_myyouku"
android:background="@null"
android:layout_alignParentBottom="true"
android:layout_marginRight="5dp"
/>
</RelativeLayout>
<!-- 三级菜单-->
<RelativeLayout
android:id="@+id/rl_level3"
android:layout_width="300dp"
android:layout_height="150dp"
android:background="@drawable/level3"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel1"
android:background="@null"
android:layout_marginLeft="5dp"
android:layout_alignParentBottom="true"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel7"
android:background="@null"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="5dp"
/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel2"
android:background="@null"
android:layout_marginLeft="25dp"
android:layout_marginTop="60dp"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel6"
android:background="@null"
android:layout_alignParentRight="true"
android:layout_marginRight="25dp"
android:layout_marginTop="60dp"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel3"
android:background="@null"
android:layout_marginLeft="60dp"
android:layout_marginTop="20dp"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel5"
android:background="@null"
android:layout_alignParentRight="true"
android:layout_marginRight="60dp"
android:layout_marginTop="20dp"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/channel4"
android:background="@null"
android:layout_centerHorizontal="true"
android:layout_marginTop="2dp"/>
</RelativeLayout>
</RelativeLayout>
效果图:
2,读取XML文件里面的控件,并为菜单添加点击事件
private boolean isOpen3 = true; //记录三级菜单是否打开
private boolean isOpen2 = true; //记录二级菜单是否打开
private RelativeLayout level3;
private RelativeLayout level2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//加载容器布局
level2 = findViewById(R.id.rl_level2);
level3 = findViewById(R.id.rl_level3);
ImageButton menu = findViewById(R.id.ib_menu);
ImageButton home = findViewById(R.id.ib_home);
//添加点击事件
menu.setOnClickListener(this);
home.setOnClickListener(this);
3,点击二级菜单的菜单按钮,隐藏或显示三级菜单
@Override
public void onClick(View v) {
//判断哪一个菜单被点击了
switch (v.getId()){
case R.id.ib_menu:
if(isOpen3){
//应该关闭菜单
close(level3,200);
}else{
//应该打开菜单
open(level3);
}
isOpen3 = !isOpen3;
break;
case R.id.ib_home:
if(isOpen3){
//如果显示三级菜单,就关闭三级菜单
close(level3,0);
isOpen3 = false;
}
if(isOpen2){
//关闭二级菜单
close(level2,200);
}else{
//打开二级菜单
open(level2);
}
isOpen2 = !isOpen2;
break;
default:
break;
}
}
4,创建anim文件,然后添加动画
创建步骤:
创建完成后再回到Android项目,在src文件夹下就会出现anim动画文件,然后再在anim文件加下配置动画的XML文件
5,封装旋转动画
public void open(RelativeLayout relativeLayout){
//打开三级菜单
Animation in = AnimationUtils.loadAnimation(this,R.anim.rotate_in_anim);
relativeLayout.startAnimation(in);
//子控件可点击
changeState(relativeLayout,true);
}
public void close(RelativeLayout relativeLayout,long dalay){
//关闭三级菜单
Animation out = AnimationUtils.loadAnimation(this,R.anim.rotate_out_anim);
out.setStartOffset(dalay); //添加延迟效果
relativeLayout.startAnimation(out);
//子控件不可点击
changeState(relativeLayout,false);
}
其中解决了补间动画的弊端:视觉效果上翻转上去了,点击原来的位置,按钮还可以响应事件。转出去就设置这个容器的所有空间都可点击;转回来的容器的所有子控件都可以点击。
public void changeState(RelativeLayout relativeLayout,boolean enable){
//获取容器子控件的个数
int childCount = relativeLayout.getChildCount();
//遍历容器的子控件
for(int i =0;i < childCount;i++){
//取出对应的子控件
View view = relativeLayout.getChildAt(i);
//设置子控件的状态
view.setEnabled(enable);
}
}
MainActivity
完整代码:
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private boolean isOpen3 = true; //记录三级菜单是否打开
private boolean isOpen2 = true; //记录二级菜单是否打开
private RelativeLayout level3;
private RelativeLayout level2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//加载容器布局
level2 = findViewById(R.id.rl_level2);
level3 = findViewById(R.id.rl_level3);
ImageButton menu = findViewById(R.id.ib_menu);
ImageButton home = findViewById(R.id.ib_home);
//添加点击事件
menu.setOnClickListener(this);
home.setOnClickListener(this);
}
@Override
public void onClick(View v) {
//判断哪一个菜单被点击了
switch (v.getId()){
case R.id.ib_menu:
if(isOpen3){
//应该关闭菜单
close(level3,200);
}else{
//应该打开菜单
open(level3);
}
isOpen3 = !isOpen3;
break;
case R.id.ib_home:
if(isOpen3){
//如果显示三级菜单,就关闭三级菜单
close(level3,0);
isOpen3 = false;
}
if(isOpen2){
//关闭二级菜单
close(level2,200);
}else{
//打开二级菜单
open(level2);
}
isOpen2 = !isOpen2;
break;
default:
break;
}
}
public void open(RelativeLayout relativeLayout){
//打开三级菜单
Animation in = AnimationUtils.loadAnimation(this,R.anim.rotate_in_anim);
relativeLayout.startAnimation(in);
//子控件可点击
changeState(relativeLayout,true);
}
public void close(RelativeLayout relativeLayout,long dalay){
//关闭三级菜单
Animation out = AnimationUtils.loadAnimation(this,R.anim.rotate_out_anim);
out.setStartOffset(dalay);
relativeLayout.startAnimation(out);
//子控件不可点击
changeState(relativeLayout,false);
}
public void changeState(RelativeLayout relativeLayout,boolean enable){
//获取容器子控件的个数
int childCount = relativeLayout.getChildCount();
//遍历容器的子控件
for(int i =0;i < childCount;i++){
//取出对应的子控件
View view = relativeLayout.getChildAt(i);
//设置子控件的状态
view.setEnabled(enable);
}
}
}
三、感悟
这个Demo虽然很简单但写起来的时候还是会出各种各样的麻烦,最难得地方就是动画旋转角度,思维不缜密,还有待加强。多多练习,熟能生巧!