zoukankan      html  css  js  c++  java
  • 【Android进阶】自定义控件实现底部扇形展开菜单效果

    这个项目是优化的其他人的,主要优化了界面菜单的显示,下面开始。

    先看效果图





    项目的总结构



    下面开始贴代码,由于必要的地方都添加了注释,所以不过多讲解


    anim_button.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
    
        <Button
            android:id="@+id/btn_sleep"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="10dp"
            android:visibility="invisible"
            android:background="@drawable/composer_sleep" />
    
        <Button
            android:id="@+id/btn_thought"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="10dp"
            android:visibility="invisible"
            android:background="@drawable/composer_thought" />
    
        <Button
            android:id="@+id/btn_music"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="10dp"
            android:visibility="invisible"
            android:background="@drawable/composer_music" />
    
        <Button
            android:id="@+id/btn_place"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="10dp"
            android:visibility="invisible"
            android:background="@drawable/composer_place" />
    
        <Button
            android:id="@+id/btn_with"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="10dp"
            android:visibility="invisible"
            android:background="@drawable/composer_with" />
    
        <Button
            android:id="@+id/btn_camera"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="10dp"
            android:visibility="invisible"
            android:background="@drawable/composer_camera" />
    
        <Button
            android:id="@+id/btn_menu"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:background="@drawable/friends_delete" />
    
    </RelativeLayout>

    主界面的布局main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
        
    	<com.example.anim.AnimButtons
    	    android:id="@+id/animButtons"
    	    android:layout_width="fill_parent"
            android:layout_height="fill_parent"
    	    />
    </LinearLayout>

    最重要的,自定义控件的实现

    AnimButtons.java

    package com.example.anim;
    
    import android.R.anim;
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.animation.Animation;
    import android.view.animation.Animation.AnimationListener;
    import android.view.animation.ScaleAnimation;
    import android.view.animation.TranslateAnimation;
    import android.widget.Button;
    import android.widget.RelativeLayout;
    
    /**
     * 底部展开菜单实现
     * 
     * @author ZhaoKaiQiang
     * 
     *         Time:2014年3月11日
     */
    public class AnimButtons extends RelativeLayout {
    
    	private Context context;
    	private int leftMargin = 0, bottomMargin = 0;
    	private final int buttonWidth = 58;// 图片宽高
    	private final int r = 180;// 半径
    	private final int maxTimeSpent = 200;// 最长动画耗时
    	private final int minTimeSpent = 80;// 最短动画耗时
    	private int intervalTimeSpent;// 每相邻2个的时间间隔
    	private Button[] btns;
    	private Button btn_menu;
    	private RelativeLayout.LayoutParams params;
    	private boolean isOpen = false;// 是否菜单打开状态
    	private float angle;// 每个按钮之间的夹角
    
    	public int bottomMargins = this.getMeasuredHeight() - buttonWidth
    			- bottomMargin;
    
    	public AnimButtons(Context context) {
    		super(context);
    		this.context = context;
    	}
    
    	public AnimButtons(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		this.context = context;
    	}
    
    	@Override
    	protected void onFinishInflate() {
    		super.onFinishInflate();
    		View view = LayoutInflater.from(context).inflate(R.layout.anim_buttons,
    				this);
    
    		initButtons(view);
    
    	}
    
    	private void initButtons(View view) {
    		// 可以根据按钮的个数自己增减
    		btns = new Button[4];
    		btns[0] = (Button) view.findViewById(R.id.btn_camera);
    		btns[1] = (Button) view.findViewById(R.id.btn_with);
    		btns[2] = (Button) view.findViewById(R.id.btn_place);
    		btns[3] = (Button) view.findViewById(R.id.btn_music);
    		// btns[4] = (Button) view.findViewById(R.id.btn_thought);
    		// btns[5] = (Button) view.findViewById(R.id.btn_sleep);
    		btn_menu = (Button) view.findViewById(R.id.btn_menu);
    
    		leftMargin = ((RelativeLayout.LayoutParams) (btn_menu.getLayoutParams())).leftMargin;
    		bottomMargin = ((RelativeLayout.LayoutParams) (btn_menu
    				.getLayoutParams())).bottomMargin;
    
    		for (int i = 0; i < btns.length; i++) {
    			// 初始化的时候按钮重合
    			btns[i].setLayoutParams(btn_menu.getLayoutParams());
    			btns[i].setTag(String.valueOf(i));
    			btns[i].setOnClickListener(clickListener);
    		}
    
    		intervalTimeSpent = (maxTimeSpent - minTimeSpent) / btns.length;
    		angle = (float) Math.PI / (2 * (btns.length - 1));
    	}
    
    	@Override
    	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    		super.onSizeChanged(w, h, oldw, oldh);
    		bottomMargins = this.getMeasuredHeight() - buttonWidth - bottomMargin;
    		btn_menu.setOnClickListener(new OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				if (!isOpen) {
    					openMenu();
    				} else {
    					closeMenu();
    				}
    			}
    		});
    
    	}
    
    	public void closeMenu() {
    		if (isOpen == true) {
    			isOpen = false;
    			for (int i = 0; i < btns.length; i++) {
    				float xLenth = (float) (r * Math.sin(i * angle));
    				float yLenth = (float) (r * Math.cos(i * angle));
    				btns[i].startAnimation(animTranslate(-xLenth, yLenth,
    						leftMargin, bottomMargins, btns[i], maxTimeSpent - i
    								* intervalTimeSpent));
    				btns[i].setVisibility(View.INVISIBLE);
    			}
    		}
    	}
    
    	public void openMenu() {
    		isOpen = true;
    		for (int i = 0; i < btns.length; i++) {
    			float xLenth = (float) (r * Math.sin(i * angle));
    			float yLenth = (float) (r * Math.cos(i * angle));
    			btns[i].startAnimation(animTranslate(xLenth, -yLenth, leftMargin
    					+ (int) xLenth, bottomMargins - (int) yLenth, btns[i],
    					minTimeSpent + i * intervalTimeSpent));
    			btns[i].setVisibility(View.VISIBLE);
    		}
    
    	}
    
    	private Animation animScale(float toX, float toY) {
    		Animation animation = new ScaleAnimation(1.0f, toX, 1.0f, toY,
    				Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
    				0.5f);
    		animation.setInterpolator(context,
    				anim.accelerate_decelerate_interpolator);
    		animation.setDuration(400);
    		animation.setFillAfter(false);
    		return animation;
    
    	}
    
    	private Animation animTranslate(float toX, float toY, final int lastX,
    			final int lastY, final Button button, long durationMillis) {
    		Animation animation = new TranslateAnimation(0, toX, 0, toY);
    		animation.setAnimationListener(new AnimationListener() {
    
    			@Override
    			public void onAnimationStart(Animation animation) {
    
    			}
    
    			@Override
    			public void onAnimationRepeat(Animation animation) {
    
    			}
    
    			@Override
    			public void onAnimationEnd(Animation animation) {
    				params = new RelativeLayout.LayoutParams(0, 0);
    				params.height = buttonWidth;
    				params.width = buttonWidth;
    				params.setMargins(lastX, lastY, 0, 0);
    				button.setLayoutParams(params);
    				button.clearAnimation();
    
    			}
    		});
    		animation.setDuration(durationMillis);
    		return animation;
    	}
    
    	View.OnClickListener clickListener = new View.OnClickListener() {
    
    		@Override
    		public void onClick(View v) {
    			int selectedItem = Integer.parseInt((String) v.getTag());
    			for (int i = 0; i < btns.length; i++) {
    				if (i == selectedItem) {
    					btns[i].startAnimation(animScale(2.0f, 2.0f));
    				} else {
    					btns[i].startAnimation(animScale(0.0f, 0.0f));
    				}
    			}
    			if (onButtonClickListener != null) {
    				onButtonClickListener.onButtonClick(v, selectedItem);
    			}
    		}
    
    	};
    
    	public boolean isOpen() {
    		return isOpen;
    	}
    
    	private OnButtonClickListener onButtonClickListener;
    
    	public interface OnButtonClickListener {
    		void onButtonClick(View v, int id);
    	}
    
    	public void setOnButtonClickListener(
    			OnButtonClickListener onButtonClickListener) {
    		this.onButtonClickListener = onButtonClickListener;
    	}
    
    }
    

    AnimButtonsActivity.java

    package com.example.anim;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Toast;
    /**
     * 主界面
     * @author 	ZhaoKaiQiang
     *			
     *			Time:2014年3月11日
     */
    public class AnimButtonsActivity extends Activity {
    
    	private AnimButtons animButtons;
    	
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.main);
    		animButtons = (AnimButtons) findViewById(R.id.animButtons);
    		animButtons
    				.setOnButtonClickListener(new AnimButtons.OnButtonClickListener() {
    					@Override
    					public void onButtonClick(View v, int id) {
    						Toast.makeText(AnimButtonsActivity.this, "id-->" + id,
    								0).show();
    						animButtons.closeMenu();
    					}
    				});
    	}
    }

    点击下载源码


    如有问题,请留言



  • 相关阅读:
    used内存较大,实际top查看系统进程中并没有占用这么多内存
    查看LINUX进程内存占用情况
    关于ConcurrentHashMap的key和value不能为null的深层次原因
    Linux修改用户所在组方法
    原因可能是托管的PInvoke签名与非托管的目标签名不匹配
    vs2019 实现C#调用c++的dll两种方法
    java jvm 参数 -Xms -Xmx -Xmn -Xss 调优总结
    java 读取文件的几种方式和通过url获取文件
    Idea中Maven的默认配置 (非常好)
    去哪儿网models数据更新
  • 原文地址:https://www.cnblogs.com/oversea201405/p/3749551.html
Copyright © 2011-2022 走看看