安卓中級教程(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. ...
随机推荐
- ngCloak 实现 Angular 初始化闪烁最佳实践
在做angular的SPA开发时,我们经常会遇见在如Chrome这类能够快速解析的浏览器上出现表达式({{ express }} ),或者是模块(div)的闪烁.对于这个问题由于JavaScript去 ...
- 交叉编译fftw
交叉编译 fftw 使用的源码是 fftw-3.2.2-arm.tar.gz 新塘平台arm ./configure --prefix=/usr/local/fftw_arm --host=arm-l ...
- 百度地图SDK
百度地图官方SDK文档 http://lbsyun.baidu.com/index.php?title=androidsdk 一.申请百度地图SDK 每一个app对应一个百度地图AK,百度地图 ...
- SoapUI 设置 request data with json body
--背景 使用WCF定义REST风格的WebService,如下: [ServiceContract] public interface INISTService { [Op ...
- js函数中this的不同含义
1.js函数调用过程中,js线程会进入新的执行环境并创建该环境的变量对象,并添加两个变量:this和arguments,因此可以在函数中使用这两个变量.需要注意的是,this变量不能重新赋值,而arg ...
- linux启动和关闭
startup,startup mount,startup nomount之间的区别: STARTUP NOMOUNT选项:(读初始化参数文件,启动实例)STARTUP NOMOUNT选项启动实例,但 ...
- C#动态创建和动态使用程序集、类、方法、字段等
C#动态创建和动态使用程序集.类.方法.字段等 分类:技术交流 (3204) (3) 首先需要知道动态创建这些类型是使用的一些什么技术呢?其实只要相关动态加载程序集呀,类呀,都是使用反射,那么动 ...
- GNU/Linux下LVM配置管理以及快照卷、物理卷、卷组、逻辑卷的创建和删除
LVM是Linux环境中对磁盘分区进行管理的一种机制,是建立在硬盘和分区之上.文件系统之下的一个逻辑层,可提高磁盘分区管理的灵活性.最大的优点是在不损伤数据的前提下调整存储空间的大小. 本篇主要讲述L ...
- 日志解析LogParse启动参数配置
-task task_stat1001to1010.yaml -log log4j_stat1001to1010.xml 用绝对路径
- Vim基础操作
在正式使用Vim之前,先来点开胃菜,学习下Vim中一些常用的命令,有了这些基本命令,才能让我们使用Vim更加得心应手,加快工作的效率~ 注意:接下来将要介绍的命令主要是用在Vim的Normal模式下. ...