Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android模塊化編程——炫酷小巧多功能Button

Android模塊化編程——炫酷小巧多功能Button

編輯:關於Android編程

前段時間客戶需求,要加幾個按鈕,包括清理緩存,關於,設置,定位等。可是界面已經做好了,再重新布局界面,很麻煩。所以做了這麼個小Button。在此分享,供大家學習。下面是幾張截圖,動畫效果沒工具保存,是依次展開的。

首先上自定義布局文件:ComposerLayout.java

package com.example.button;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

@SuppressLint("ViewConstructor")
public class ComposerLayout extends RelativeLayout {

public static byte RIGHTBOTTOM = 1, CENTERBOTTOM = 2, LEFTBOTTOM = 3,
LEFTCENTER = 4, LEFTTOP = 5, CENTERTOP = 6, RIGHTTOP = 7,
RIGHTCENTER = 8;
private boolean hasInit = false;
private boolean areButtonsShowing = false;
private Context mycontext;
private ImageView cross;
private RelativeLayout rlButton;
private Animations myani;
private LinearLayout[] llayouts;
private int duretime = 300;

public ComposerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.mycontext = context;
}

public ComposerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.mycontext = context;
}

public ComposerLayout(Context context) {
super(context);
this.mycontext = context;
}

/**
* 初始化
*
* @param imgResId
* 子按鈕圖片drawable的id
* @param showhideButtonId
* 主按鈕drawable的id
* @param crossId
* 主按鈕上面十字片drawable的id
* @param pCode
* 位置代碼,例如“右上角”ALIGN_PARENT_BOTTOM|ALIGN_PARENT_RIGHT
* @param radius
*
* @param durationMillis
* 動畫耗時
*/
public void init(int[] imgResId, int showhideButtonId, int crossId,
byte pCode, int radius, final int durationMillis) {
duretime = durationMillis;
int align1 = 12, align2 = 14;
if (pCode == RIGHTBOTTOM) { // 右下角
align1 = ALIGN_PARENT_RIGHT;
align2 = ALIGN_PARENT_BOTTOM;
} else if (pCode == CENTERBOTTOM) {// 中下
align1 = CENTER_HORIZONTAL;
align2 = ALIGN_PARENT_BOTTOM;
} else if (pCode == LEFTBOTTOM) { // 左下角
align1 = ALIGN_PARENT_LEFT;
align2 = ALIGN_PARENT_BOTTOM;
} else if (pCode == LEFTCENTER) { // 左中
align1 = ALIGN_PARENT_LEFT;
align2 = CENTER_VERTICAL;
} else if (pCode == LEFTTOP) { // 左上角
align1 = ALIGN_PARENT_LEFT;
align2 = ALIGN_PARENT_TOP;
} else if (pCode == CENTERTOP) { // 中上
align1 = CENTER_HORIZONTAL;
align2 = ALIGN_PARENT_TOP;
} else if (pCode == RIGHTTOP) { // 右上角
align1 = ALIGN_PARENT_RIGHT;
align2 = ALIGN_PARENT_TOP;
} else if (pCode == RIGHTCENTER) { // 右中
align1 = ALIGN_PARENT_RIGHT;
align2 = CENTER_VERTICAL;
}
// 處理半徑
RelativeLayout.LayoutParams thislps = (LayoutParams) this
.getLayoutParams();
Bitmap mBottom = BitmapFactory.decodeResource(mycontext.getResources(),
imgResId[0]);
if (pCode == CENTERBOTTOM || pCode == CENTERTOP) {
if (thislps.width != -1
&& thislps.width != -2
&& thislps.width < (radius + mBottom.getWidth() + radius * 0.1) * 2) {
thislps.width = (int) ((radius * 1.1 + mBottom.getWidth()) * 2);
}
} else {
if (thislps.width != -1
&& thislps.width != -2
&& thislps.width < radius + mBottom.getWidth() + radius
* 0.1) {
thislps.width = (int) (radius * 1.1 + mBottom.getWidth());
}
}
if (pCode == LEFTCENTER || pCode == RIGHTCENTER) {
if (thislps.height != -1
&& thislps.height != -2
&& thislps.height < (radius + mBottom.getHeight() + radius * 0.1) * 2) {
thislps.width = (int) ((radius * 1.1 + mBottom.getHeight()) * 2);
}
} else {
if (thislps.height != -1
&& thislps.height != -2
&& thislps.height < radius + mBottom.getHeight() + radius
* 0.1) {
thislps.height = (int) (radius * 1.1 + mBottom.getHeight());
}
}
this.setLayoutParams(thislps);
RelativeLayout rl1 = new RelativeLayout(mycontext);// 包含若干子按鈕

rlButton = new RelativeLayout(mycontext); // 主按扭
llayouts = new LinearLayout[imgResId.length];
// N個子按鈕
for (int i = 0; i < imgResId.length; i++) {
ImageView img = new ImageView(mycontext);// 子按扭圖片

img.setImageResource(imgResId[i]);
LinearLayout.LayoutParams llps = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);

img.setLayoutParams(llps);
llayouts[i] = new LinearLayout(mycontext);// 子按鈕
llayouts[i].setId(100 + i);// 隨便設個id,方便onclick的時候識別。隨便設,如果發現同其他控件沖突就自行改一下。
llayouts[i].addView(img);

RelativeLayout.LayoutParams rlps = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
rlps.alignWithParent = true;
rlps.addRule(align1, RelativeLayout.TRUE);
rlps.addRule(align2, RelativeLayout.TRUE);
llayouts[i].setLayoutParams(rlps);
llayouts[i].setVisibility(View.INVISIBLE);// 此處不能為GONE
rl1.addView(llayouts[i]);
}
RelativeLayout.LayoutParams rlps1 = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT);
rlps1.alignWithParent = true;
rlps1.addRule(align1, RelativeLayout.TRUE);
rlps1.addRule(align2, RelativeLayout.TRUE);
rl1.setLayoutParams(rlps1);

RelativeLayout.LayoutParams buttonlps = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
buttonlps.alignWithParent = true;
buttonlps.addRule(align1, RelativeLayout.TRUE);
buttonlps.addRule(align2, RelativeLayout.TRUE);
rlButton.setLayoutParams(buttonlps);
rlButton.setBackgroundResource(showhideButtonId);
cross = new ImageView(mycontext);
cross.setImageResource(crossId);
RelativeLayout.LayoutParams crosslps = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
crosslps.alignWithParent = true;
crosslps.addRule(CENTER_IN_PARENT, RelativeLayout.TRUE);
cross.setLayoutParams(crosslps);
rlButton.addView(cross);
myani = new Animations(rl1, pCode, radius);
rlButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (areButtonsShowing) {
myani.startAnimationsOut(duretime);
cross.startAnimation(Animations.getRotateAnimation(-270,
0, duretime));
} else {
myani.startAnimationsIn(duretime);
cross.startAnimation(Animations.getRotateAnimation(0,
-270, duretime));
}
areButtonsShowing = !areButtonsShowing;
}
});

cross.startAnimation(Animations.getRotateAnimation(0, 360, 200));
this.addView(rl1);
this.addView(rlButton);
hasInit = true;

}

public void collapse() {
myani.startAnimationsOut(duretime);
cross.startAnimation(Animations.getRotateAnimation(-270, 0, duretime));
areButtonsShowing = false;
}

public void expand() {
myani.startAnimationsIn(duretime);
cross.startAnimation(Animations.getRotateAnimation(0, -270, duretime));
areButtonsShowing = true;
}

public boolean isInit() {
return hasInit;
}

public boolean isShow() {
return areButtonsShowing;
}

/**
* 設置各子按鈕OnClick事件
*/
public void setButtonsOnClickListener(final OnClickListener l) {

if (llayouts != null) {
for (int i = 0; i < llayouts.length; i++) {
if (llayouts[i] != null)
llayouts[i].setOnClickListener(new OnClickListener() {

@Override
public void onClick(final View view) {
//此處添加其他事件比如按鈕增大或者縮回菜單
collapse();
l.onClick(view);
}

});
}
}
}
}
這裡自定義了一個BaseActivity,使用BaseActivity的好處不用我說了吧:

package com.example.button;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

public abstract class BaseActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setView();
initView();
setListener();
initData();
}

@Override
protected void onResume() {
super.onResume();
}

@Override
protected void onPause() {
super.onPause();
}

/**
* 設置布局文件
*/
public abstract void setView();

/**
* 初始化布局文件中的控件
*/
public abstract void initView();

/**
* 設置控件的監聽
*/
public abstract void setListener();

private void initData() {
String appID = "wx88818f8c48a95eb4";
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}

}
動畫設置類,Animations,這裡用了一個開源動畫庫nineoldandroids.jar。下載文末原代碼中有

package com.example.button;

import static com.nineoldandroids.view.ViewPropertyAnimator.animate;

import java.util.ArrayList;
import java.util.List;

import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.LinearLayout;

import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.Animator.AnimatorListener;
import com.nineoldandroids.view.ViewPropertyAnimator;

public class Animations {
public final int R; // 半徑
public static byte RIGHTBOTTOM = 1, CENTERBOTTOM = 2, LEFTBOTTOM = 3,
LEFTCENTER = 4, LEFTTOP = 5, CENTERTOP = 6, RIGHTTOP = 7,
RIGHTCENTER = 8;

private int pc; // 位置代號
private ViewGroup clayout; // 父layout
private final int amount; // 有幾多個按鈕
private double fullangle = 180.0;// 在幾大嘅角度內排佈
private byte xOri = 1, yOri = 1; // x、y值嘅方向,即系向上還是向下
private boolean isOpen = false;// 記錄是已經打開還是關閉
private List<ViewPropertyAnimator> viewAnimators = new ArrayList<ViewPropertyAnimator>();

/**
* 構造函數
*
* @param comlayout
* 包裹彈出按鈕嘅layout
* @param poscode
* 位置代號,分別對應RIGHTBOTTOM、CENTERBOTTOM、LEFTBOTTOM、LEFTCENTER、
* LEFTTOP、CENTERTOP、RIGHTTOP、RIGHTCENTER
* @param radius
* 半徑
*/
public Animations(ViewGroup comlayout, int poscode, int radius) {
this.pc = poscode;
this.clayout = comlayout;
this.amount = clayout.getChildCount();
this.R = radius;

// 初始化動畫,每個view對應一個animator
for (int i = 0; i < amount; i++) {
View childAt = clayout.getChildAt(i);
ViewPropertyAnimator anim = animate(childAt);
viewAnimators.add(anim);
}

if (poscode == RIGHTBOTTOM) { // 右下角
fullangle = 90;
xOri = -1;
yOri = -1;
} else if (poscode == CENTERBOTTOM) {// 中下
fullangle = 180;
xOri = -1;
yOri = -1;
} else if (poscode == LEFTBOTTOM) { // 左下角
fullangle = 90;
xOri = 1;
yOri = -1;
} else if (poscode == LEFTCENTER) { // 左中
fullangle = 180;
xOri = 1;
yOri = -1;
} else if (poscode == LEFTTOP) { // 左上角
fullangle = 90;
xOri = 1;
yOri = 1;
} else if (poscode == CENTERTOP) { // 中上
fullangle = 180;
xOri = -1;
yOri = 1;
} else if (poscode == RIGHTTOP) { // 右上角
fullangle = 90;
xOri = -1;
yOri = 1;
} else if (poscode == RIGHTCENTER) { // 右中
fullangle = 180;
xOri = -1;
yOri = -1;
}
}

private class AnimListener implements AnimatorListener {

private View target;

public AnimListener(View _target) {
target = _target;
}

@Override
public void onAnimationStart(Animator animation) {

}

@Override
public void onAnimationEnd(Animator animation) {
if (!isOpen) {
target.setVisibility(View.INVISIBLE);
}
}

@Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub

}

@Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub

}
}

<pre name="code" class="java"> /**
* 開
*/public void startAnimationsIn(int durationMillis) {isOpen = true;for (int i = 0; i < clayout.getChildCount(); i++) {final LinearLayout inoutimagebutton = (LinearLayout) clayout.getChildAt(i);double offangle = fullangle / (amount - 1);final double
deltaY, deltaX;if (pc == LEFTCENTER || pc == RIGHTCENTER) {deltaX = Math.sin(offangle * i * Math.PI / 180) * R;deltaY = Math.cos(offangle * i * Math.PI / 180) * R;} else {deltaY = Math.sin(offangle * i * Math.PI / 180) * R;deltaX = Math.cos(offangle * i *
Math.PI / 180) * R;}ViewPropertyAnimator viewPropertyAnimator = viewAnimators.get(i);viewPropertyAnimator.setListener(null);inoutimagebutton.setVisibility(View.VISIBLE);viewPropertyAnimator.x((float) (inoutimagebutton.getLeft() + xOri * deltaX)).y((float)
(inoutimagebutton.getTop() + yOri * deltaY));}}/** * 收 */public void startAnimationsOut(int durationMillis) {isOpen = false;for (int i = 0; i < clayout.getChildCount(); i++) {final LinearLayout inoutimagebutton = (LinearLayout) clayout.getChildAt(i);ViewPropertyAnimator
viewPropertyAnimator = viewAnimators.get(i);viewPropertyAnimator.setListener(null);viewPropertyAnimator.x((float) inoutimagebutton.getLeft()).y((float) inoutimagebutton.getTop());viewPropertyAnimator.setListener(new AnimListener(inoutimagebutton));}}public
int getPosCode() {return this.pc;}/** * 自轉函數 * * @param fromDegrees * 從多少度 * @param toDegrees * 到多少度 * @param durationMillis * m */public static Animation getRotateAnimation(float fromDegrees,float toDegrees, int durationMillis) {RotateAnimation rotate = new
RotateAnimation(fromDegrees, toDegrees,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);rotate.setDuration(durationMillis);rotate.setFillAfter(true);return rotate;}}

主Activity:TestActivity

package com.example.button;

import android.view.View;
import android.view.View.OnClickListener;
import android.widget.RelativeLayout;
import android.widget.Toast;

public class TestActivity extends BaseActivity {

private ComposerLayout clayout;
@Override
public void setView() {
setContentView(R.layout.activity_main);

}

@Override
public void initView() {
// 引用控件
clayout = (ComposerLayout) findViewById(R.id.test);
clayout.init(new int[] { R.drawable.composer_camera,
R.drawable.composer_music, R.drawable.composer_place,
R.drawable.composer_sleep, R.drawable.composer_thought,
R.drawable.composer_with }, R.drawable.composer_button,
R.drawable.composer_icn_plus, ComposerLayout.RIGHTCENTER, 180,
300);

}

@Override
public void setListener() {
// 點擊事件監聽,100+0對應composer_camera,100+1對應composer_music……如此類推你有機個按鈕就加幾個按鈕都行。
OnClickListener clickit = new OnClickListener() {
@Override
public void onClick(View v) {
if (v.getId() == 100 + 0) {
Toast.makeText(TestActivity.this, "測試A", 0).show();
} else if (v.getId() == 100 + 1) {
Toast.makeText(TestActivity.this, "測試B...", 0).show();
} else if (v.getId() == 100 + 2) {
Toast.makeText(TestActivity.this, "測試C...", 0).show();
} else if (v.getId() == 100 + 3) {
Toast.makeText(TestActivity.this, "測試D...", 0).show();
} else if (v.getId() == 100 + 4) {
Toast.makeText(TestActivity.this, "測試E...", 0).show();
} else if (v.getId() == 100 + 5) {
Toast.makeText(TestActivity.this, "測試F..", 0).show();
}
}
};
clayout.setButtonsOnClickListener(clickit);

RelativeLayout rl = (RelativeLayout) findViewById(R.id.rlparent);
rl.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(TestActivity.this, "父控件可以點擊的哦!!!", 0).show();
System.out.println("父控件可以點擊。");
}
});

}

}

這裡自定義了一個BaseActivity,使用BaseActivity的好處不用我說了吧:

 

 

package com.example.button;


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

public abstract class BaseActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setView();
		initView();
		setListener();
		initData();
	}
	
	@Override
	protected void onResume() {
		super.onResume();
	}
	
	@Override
	protected void onPause() {
		super.onPause();
	}

	/**
	 * 設置布局文件
	 */
	public abstract void setView();

	/**
	 * 初始化布局文件中的控件
	 */
	public abstract void initView();

	/**
	 * 設置控件的監聽
	 */
	public abstract void setListener();
	
	private void initData() {
		String appID = "wx88818f8c48a95eb4";
	}
	@Override 
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	    super.onActivityResult(requestCode, resultCode, data);
	}
	
	
	
	
	
}
動畫設置類,Animations,這裡用了一個開源動畫庫nineoldandroids.jar。下載文末原代碼中有
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rlparent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ABCDEF" >

<com.example.button.ComposerLayout
android:id="@+id/test"
android:layout_width="20dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" >
</com.example.button.ComposerLayout>

</RelativeLayout>
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved