安卓中級教程(9):pathbutton中的animation.java研究(2)
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
安卓中級教程(9):pathbutton中的animation.java研究(2)的更多相关文章
- 安卓中級教程(3):ScrollView
以上是scrollview的圖例,可見srollview是一種滑動功能的控件,亦是非常常見的控件. 一般寫法如下: package com.mycompany.viewscroller; import ...
- 安卓中級教程(8):pathbutton中的animation.java研究(1)
src/geniuz/myPathbutton/myAnimations.java package geniuz.myPathbutton; import java.util.ArrayList; i ...
- 安卓中級教程(10):@InjectView
package com.example.android.db01; import android.app.Activity; import android.content.ContentValues; ...
- 安卓中級教程(5):ScrollView與refreshable之間的設置
設置向下拉動更新. package com.mycompany.Scroll_test; import android.app.*; import android.os.*; import andro ...
- 安卓中級教程(4):ScrollView與ListView之間的高度問題
在scrollView中加插ListView是一個大難題.其中一個難題是Listview的高度難以計算,輸出效果往往強差人意,就讓我們看看當中的問題 . <LinearLayout xmlns: ...
- 安卓中級教程(6):annotation的基本用法
package com.example.ele_me.activity; import android.annotation.SuppressLint; import android.app.Acti ...
- 安卓中級教程(1):@InjectView
package com.mycompany.hungry; import android.annotation.SuppressLint; import android.app.Activity; i ...
- 安卓中級教程(11):深入研究餓了麼的各個java檔運作關係(1)
package com.example.ele_me.activity; import android.annotation.SuppressLint; import android.app.Acti ...
- 安卓中級教程(7):annotation中的 public @interface的用法
package com.example.ele_me.util; import java.lang.annotation.Retention; import java.lang.annotation. ...
随机推荐
- ms-dos中 MSCDEX命名语法详解
一.MSCDEX的语法及参数: MSCDEX可以在AUTOEXEC.BAT文件中自动加载,也可以在DOS的命令行中载入但要使用光驱,前提条件是在Config.sys文件中加载了光驱的驱动 ...
- error 502 in ngin php5-fpm
unix:/var/run/php5-fpm.sock failed (11: Resource temporarily unavailable) http://stackoverflow.com/q ...
- tomcat不安全因素
tomcat的提供了一个非常方便的manager系统,可以远程上传war项目,运行项目,但是这也是一个非常危险的地方,我曾经开发过一块B/S架构的小系统,提供了本地文件扫描,文件浏览,扫描等功能,并且 ...
- WEB API异常处理
当一个web api抛出一个异常后 此异常会被转化成一个HTTP响应 错误代码为500的服务错误 但是如果你不想让客户端看到500的错误码 你也可以自定义错误码 如下代码当用户输入的ID没有与之相关的 ...
- nginx访问不了zabbix安装配置界面
通过yum安装的php等其他各种软件,配置好后,html目录下面php可以解析,但是就是访问不到setup.php文件.后来各种查找,发现是setup解析错误 PHP Parse error: sy ...
- Java JVM类加载机制
虚拟机的类加载机制是:JVM把描述类的数据从.class文件加载到内存,并对数据进行校验.解析.初始化,最终形成可以被JVM直接使用的Java类型. 加载.连接(验证.准备.解析).初始化.使用.卸载 ...
- android so调试时遇到的坑 - arm流水线
直接看下面这段ARM汇编: 此时运行到的代码为ADD R3,PC 此时看一下寄存器窗口的值: 按理来说执行完ADD R3,PC后的效果应该是R3=R3+PC ,R3=40A1D5C8 但是我们可以执行 ...
- C Primer Plus_第8章_字符输入输出和输入确认_编程练习
1.题略 #include <stdio.h> int main(void) { ; printf("Please enter text here(end with Ctrl + ...
- Memcache之内存分配机制
可参见:http://blog.csdn.net/hguisu/article/details/7353482
- Select查询执行顺序
链接:http://blog.jobbole.com/55086/ 很多程序员视 SQL 为洪水猛兽.SQL 是一种为数不多的声明性语言,它的运行方式完全不同于我们所熟知的命令行语言.面向对象的程序语 ...