src/geniuz/myPathbutton/composerLayout.java

 package geniuz.myPathbutton;

 import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.Animator.AnimatorListener;
import com.nineoldandroids.view.ViewPropertyAnimator; import android.R;
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.view.animation.ScaleAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import static com.nineoldandroids.view.ViewPropertyAnimator.animate; @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 myAnimations myani; // 動畫類
private LinearLayout[] llayouts; // 子按鈕集
private int duretime = 300; /**
* 構造函數 本來想喺構造函數度讀取參數嘅,但就要喺values下面搞個attr,同埋layout嘅xml又要加命名空間————
* 咁搞嘅話~好多人可能唔知點用,而且參數太多(例如N個子按鈕)處理起身亦比較羅嗦。
* 所以而家乾脆搞個init()函數,由java代碼調用,唔讀xml喇。 所以構造函數只記錄個context就算
*/
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
* 子按鈕嘅圖片drawalbe嘅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;
// 處理pcode,將自定義嘅位置值改成align值
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) { // -1係FILL_PARENT,-2係WRAP_CONTENT
// 因為animation嘅setInterpolator設咗OvershootInterpolator,即系喐到目標之後仍然行多一段(超過目標位置)~然後再縮返到目標位置,所以父layout就要再放大少少。而因為呢個OvershootInterpolator接納嘅係一個彈力(浮點)值,佢經過一定算法計算出個時間……如果要根據呢個彈力轉換做距離數值,就比較麻煩,所以我只系求其加咗1/10個半徑。想追求完美嘅~可以自行研究下OvershootInterpolator類同Animation類,http://www.oschina.net可以揾倒android
// sdk嘅源碼。
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嘅時候識別返出嚟。呢個id值係求其設嘅,如果發現同其他控件沖突就自行改一下。
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 myAnimations(rl1, pCode, radius);
rlButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (areButtonsShowing) {
myani.startAnimationsOut(duretime);
cross.startAnimation(myAnimations.getRotateAnimation(-270,
0, duretime));
} else {
myani.startAnimationsIn(duretime);
cross.startAnimation(myAnimations.getRotateAnimation(0,
-270, duretime));
}
areButtonsShowing = !areButtonsShowing;
}
}); cross.startAnimation(myAnimations.getRotateAnimation(0, 360, 200));
this.addView(rl1);
this.addView(rlButton);
hasInit = true; } /**
* 收埋
*/
public void collapse() {
myani.startAnimationsOut(duretime);
cross.startAnimation(myAnimations.getRotateAnimation(-270, 0, duretime));
areButtonsShowing = false;
} /**
* 打開
*/
public void expand() {
myani.startAnimationsIn(duretime);
cross.startAnimation(myAnimations.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);
} });
}
}
}
}
Desktop version

最新文章

  1. python学习笔记-进程线程
  2. 【Python大系】Python快速教程
  3. mybatis 如何使用乐观锁
  4. std::map用法
  5. 17.4---返回max,不用if
  6. 报错:严重: Servlet.service() for servlet [jsp] in context with path [/20161116-Struts2-6] threw exception [/index.jsp (line: 13, column: 20) No tag &quot;textfiled&quot; defined in tag library imported with prefix
  7. 单例(C#版)
  8. 如何选中一个Checkbox,设置无效?
  9. java-excel导出
  10. hibernate_validator_06
  11. java与.net比较学习系列(3) 基本数据类型和类型转换
  12. javascript笔记整理(流程控制)
  13. SVG基础以及使用Javascript DOM操作SVG
  14. svg制作风车旋转
  15. MVC4.0,并完美结合Razor引擎
  16. Base64Util 工具类
  17. JNI探秘-----你不知道的FileInputStream的秘密
  18. 使用 IntraWeb (25) - 基本控件之 TIWRegion
  19. Confluence 6 为用户管理连接 Confluence 到 Crowd
  20. cocos2dx 3.3将坐标由父空间转化到局部空间

热门文章

  1. Shell入门教程:流程控制(6)while 循环
  2. shell--3.运算符
  3. 问题--feed列表有新闻重复的问题
  4. java基础知识(四)java内存机制
  5. 数组去重及数组的prototype原型
  6. socket的IO多路复用
  7. zend studio 做前端推荐安装的插件
  8. placeholer 换行
  9. AngularJS多模块开发
  10. caffe初试(一)happynear的caffe-windows版本的配置及遇到的问题