1. src/geniuz/myPathbutton/composerLayout.java
  2.  
  3. package geniuz.myPathbutton;
  4.  
  5. import com.nineoldandroids.animation.Animator;
  6. import com.nineoldandroids.animation.Animator.AnimatorListener;
  7. import com.nineoldandroids.view.ViewPropertyAnimator;
  8.  
  9. import android.R;
  10. import android.annotation.SuppressLint;
  11. import android.content.Context;
  12. import android.graphics.Bitmap;
  13. import android.graphics.BitmapFactory;
  14. import android.util.AttributeSet;
  15. import android.view.View;
  16. import android.view.animation.ScaleAnimation;
  17. import android.widget.ImageView;
  18. import android.widget.LinearLayout;
  19. import android.widget.RelativeLayout;
  20. import static com.nineoldandroids.view.ViewPropertyAnimator.animate;
  21.  
  22. @SuppressLint("ViewConstructor")
  23. public class composerLayout extends RelativeLayout {
  24.  
  25. public static byte RIGHTBOTTOM = 1, CENTERBOTTOM = 2, LEFTBOTTOM = 3,
  26. LEFTCENTER = 4, LEFTTOP = 5, CENTERTOP = 6, RIGHTTOP = 7,
  27. RIGHTCENTER = 8;
  28. private boolean hasInit = false; // 初始化咗未
  29. private boolean areButtonsShowing = false;// 有冇展開
  30. private Context mycontext;
  31. private ImageView cross; // 主按鈕中間嗰個十字
  32. private RelativeLayout rlButton;// 主按鈕
  33. private myAnimations myani; // 動畫類
  34. private LinearLayout[] llayouts; // 子按鈕集
  35. private int duretime = 300;
  36.  
  37. /**
  38. * 構造函數 本來想喺構造函數度讀取參數嘅,但就要喺values下面搞個attr,同埋layout嘅xml又要加命名空間————
  39. * 咁搞嘅話~好多人可能唔知點用,而且參數太多(例如N個子按鈕)處理起身亦比較羅嗦。
  40. * 所以而家乾脆搞個init()函數,由java代碼調用,唔讀xml喇。 所以構造函數只記錄個context就算
  41. */
  42. public composerLayout(Context context, AttributeSet attrs, int defStyle) {
  43. super(context, attrs, defStyle);
  44. this.mycontext = context;
  45. }
  46.  
  47. public composerLayout(Context context, AttributeSet attrs) {
  48. super(context, attrs);
  49. this.mycontext = context;
  50. }
  51.  
  52. public composerLayout(Context context) {
  53. super(context);
  54. this.mycontext = context;
  55. }
  56.  
  57. /**
  58. * 初始化
  59. *
  60. * @param imgResId
  61. * 子按鈕嘅圖片drawalbe嘅id[]
  62. * @param showhideButtonId
  63. * 主按鈕嘅圖片drawable嘅id
  64. * @param crossId
  65. * 主按鈕上面嗰個轉動十字嘅圖片drawable嘅id
  66. * @param pCode
  67. * 位置代碼,例如“右上角”係ALIGN_PARENT_BOTTOM|ALIGN_PARENT_RIGHT
  68. * @param radius
  69. * 半徑
  70. * @param durationMillis
  71. * 動畫耗時
  72. */
  73. public void init(int[] imgResId, int showhideButtonId, int crossId,
  74. byte pCode, int radius, final int durationMillis) {
  75. duretime = durationMillis;
  76. // 處理pcode,將自定義嘅位置值改成align值
  77. int align1 = 12, align2 = 14;
  78. if (pCode == RIGHTBOTTOM) { // 右下角
  79. align1 = ALIGN_PARENT_RIGHT;
  80. align2 = ALIGN_PARENT_BOTTOM;
  81. } else if (pCode == CENTERBOTTOM) {// 中下
  82. align1 = CENTER_HORIZONTAL;
  83. align2 = ALIGN_PARENT_BOTTOM;
  84. } else if (pCode == LEFTBOTTOM) { // 左下角
  85. align1 = ALIGN_PARENT_LEFT;
  86. align2 = ALIGN_PARENT_BOTTOM;
  87. } else if (pCode == LEFTCENTER) { // 左中
  88. align1 = ALIGN_PARENT_LEFT;
  89. align2 = CENTER_VERTICAL;
  90. } else if (pCode == LEFTTOP) { // 左上角
  91. align1 = ALIGN_PARENT_LEFT;
  92. align2 = ALIGN_PARENT_TOP;
  93. } else if (pCode == CENTERTOP) { // 中上
  94. align1 = CENTER_HORIZONTAL;
  95. align2 = ALIGN_PARENT_TOP;
  96. } else if (pCode == RIGHTTOP) { // 右上角
  97. align1 = ALIGN_PARENT_RIGHT;
  98. align2 = ALIGN_PARENT_TOP;
  99. } else if (pCode == RIGHTCENTER) { // 右中
  100. align1 = ALIGN_PARENT_RIGHT;
  101. align2 = CENTER_VERTICAL;
  102. }
  103. // 如果細過半徑就整大佢
  104. RelativeLayout.LayoutParams thislps = (LayoutParams) this
  105. .getLayoutParams();
  106. Bitmap mBottom = BitmapFactory.decodeResource(mycontext.getResources(),
  107. imgResId[0]);
  108. if (pCode == CENTERBOTTOM || pCode == CENTERTOP) {
  109. if (thislps.width != -1
  110. && thislps.width != -2
  111. && thislps.width < (radius + mBottom.getWidth() + radius * 0.1) * 2) {
  112. thislps.width = (int) ((radius * 1.1 + mBottom.getWidth()) * 2);
  113. }
  114. } else {
  115. if (thislps.width != -1
  116. && thislps.width != -2
  117. && thislps.width < radius + mBottom.getWidth() + radius
  118. * 0.1) { // -1係FILL_PARENT,-2係WRAP_CONTENT
  119. // 因為animation嘅setInterpolator設咗OvershootInterpolator,即系喐到目標之後仍然行多一段(超過目標位置)~然後再縮返到目標位置,所以父layout就要再放大少少。而因為呢個OvershootInterpolator接納嘅係一個彈力(浮點)值,佢經過一定算法計算出個時間……如果要根據呢個彈力轉換做距離數值,就比較麻煩,所以我只系求其加咗1/10個半徑。想追求完美嘅~可以自行研究下OvershootInterpolator類同Animation類,http://www.oschina.net可以揾倒android
  120. // sdk嘅源碼。
  121. thislps.width = (int) (radius * 1.1 + mBottom.getWidth());
  122. }
  123. }
  124. if (pCode == LEFTCENTER || pCode == RIGHTCENTER) {
  125. if (thislps.height != -1
  126. && thislps.height != -2
  127. && thislps.height < (radius + mBottom.getHeight() + radius * 0.1) * 2) {
  128. thislps.width = (int) ((radius * 1.1 + mBottom.getHeight()) * 2);
  129. }
  130. } else {
  131. if (thislps.height != -1
  132. && thislps.height != -2
  133. && thislps.height < radius + mBottom.getHeight() + radius
  134. * 0.1) {
  135. thislps.height = (int) (radius * 1.1 + mBottom.getHeight());
  136. }
  137. }
  138. this.setLayoutParams(thislps);
  139. // 兩個主要層
  140. RelativeLayout rl1 = new RelativeLayout(mycontext);// 包含若干子按鈕嘅層
  141.  
  142. rlButton = new RelativeLayout(mycontext); // 主按扭
  143. llayouts = new LinearLayout[imgResId.length];
  144. // N個子按鈕
  145. for (int i = 0; i < imgResId.length; i++) {
  146. ImageView img = new ImageView(mycontext);// 子按扭圖片
  147.  
  148. img.setImageResource(imgResId[i]);
  149. LinearLayout.LayoutParams llps = new LinearLayout.LayoutParams(
  150. LinearLayout.LayoutParams.WRAP_CONTENT,
  151. LinearLayout.LayoutParams.WRAP_CONTENT);
  152.  
  153. img.setLayoutParams(llps);
  154. llayouts[i] = new LinearLayout(mycontext);// 子按鈕層
  155. llayouts[i].setId(100 + i);// 隨便設個id,方便onclick嘅時候識別返出嚟。呢個id值係求其設嘅,如果發現同其他控件沖突就自行改一下。
  156. llayouts[i].addView(img);
  157.  
  158. RelativeLayout.LayoutParams rlps = new RelativeLayout.LayoutParams(
  159. RelativeLayout.LayoutParams.WRAP_CONTENT,
  160. RelativeLayout.LayoutParams.WRAP_CONTENT);
  161. rlps.alignWithParent = true;
  162. rlps.addRule(align1, RelativeLayout.TRUE);
  163. rlps.addRule(align2, RelativeLayout.TRUE);
  164. llayouts[i].setLayoutParams(rlps);
  165. llayouts[i].setVisibility(View.INVISIBLE);// 此处不能为GONE
  166. rl1.addView(llayouts[i]);
  167. }
  168. RelativeLayout.LayoutParams rlps1 = new RelativeLayout.LayoutParams(
  169. RelativeLayout.LayoutParams.FILL_PARENT,
  170. RelativeLayout.LayoutParams.FILL_PARENT);
  171. rlps1.alignWithParent = true;
  172. rlps1.addRule(align1, RelativeLayout.TRUE);
  173. rlps1.addRule(align2, RelativeLayout.TRUE);
  174. rl1.setLayoutParams(rlps1);
  175.  
  176. RelativeLayout.LayoutParams buttonlps = new RelativeLayout.LayoutParams(
  177. RelativeLayout.LayoutParams.WRAP_CONTENT,
  178. RelativeLayout.LayoutParams.WRAP_CONTENT);
  179. buttonlps.alignWithParent = true;
  180. buttonlps.addRule(align1, RelativeLayout.TRUE);
  181. buttonlps.addRule(align2, RelativeLayout.TRUE);
  182. rlButton.setLayoutParams(buttonlps);
  183. rlButton.setBackgroundResource(showhideButtonId);
  184. cross = new ImageView(mycontext);
  185. cross.setImageResource(crossId);
  186. RelativeLayout.LayoutParams crosslps = new RelativeLayout.LayoutParams(
  187. RelativeLayout.LayoutParams.WRAP_CONTENT,
  188. RelativeLayout.LayoutParams.WRAP_CONTENT);
  189. crosslps.alignWithParent = true;
  190. crosslps.addRule(CENTER_IN_PARENT, RelativeLayout.TRUE);
  191. cross.setLayoutParams(crosslps);
  192. rlButton.addView(cross);
  193. myani = new myAnimations(rl1, pCode, radius);
  194. rlButton.setOnClickListener(new OnClickListener() {
  195. @Override
  196. public void onClick(View v) {
  197. if (areButtonsShowing) {
  198. myani.startAnimationsOut(duretime);
  199. cross.startAnimation(myAnimations.getRotateAnimation(-270,
  200. 0, duretime));
  201. } else {
  202. myani.startAnimationsIn(duretime);
  203. cross.startAnimation(myAnimations.getRotateAnimation(0,
  204. -270, duretime));
  205. }
  206. areButtonsShowing = !areButtonsShowing;
  207. }
  208. });
  209.  
  210. cross.startAnimation(myAnimations.getRotateAnimation(0, 360, 200));
  211. this.addView(rl1);
  212. this.addView(rlButton);
  213. hasInit = true;
  214.  
  215. }
  216.  
  217. /**
  218. * 收埋
  219. */
  220. public void collapse() {
  221. myani.startAnimationsOut(duretime);
  222. cross.startAnimation(myAnimations.getRotateAnimation(-270, 0, duretime));
  223. areButtonsShowing = false;
  224. }
  225.  
  226. /**
  227. * 打開
  228. */
  229. public void expand() {
  230. myani.startAnimationsIn(duretime);
  231. cross.startAnimation(myAnimations.getRotateAnimation(0, -270, duretime));
  232. areButtonsShowing = true;
  233. }
  234.  
  235. /**
  236. * 初始化咗未(其實冇乜用,原來有就保留)
  237. */
  238. public boolean isInit() {
  239. return hasInit;
  240. }
  241.  
  242. /**
  243. * 有冇展開(其實冇乜用,原來有就保留)
  244. */
  245. public boolean isShow() {
  246. return areButtonsShowing;
  247. }
  248.  
  249. /**
  250. * 設置各子按鈕嘅onclick事件
  251. */
  252. public void setButtonsOnClickListener(final OnClickListener l) {
  253.  
  254. if (llayouts != null) {
  255. for (int i = 0; i < llayouts.length; i++) {
  256. if (llayouts[i] != null)
  257. llayouts[i].setOnClickListener(new OnClickListener() {
  258.  
  259. @Override
  260. public void onClick(final View view) {
  261. //此处添加其他事件比如按钮增大或者缩回菜单
  262. collapse();
  263. l.onClick(view);
  264. }
  265.  
  266. });
  267. }
  268. }
  269. }
  270. }
  271. Desktop version

安卓中級教程(9):pathbutton中的animation.java研究(2)的更多相关文章

  1. 安卓中級教程(3):ScrollView

    以上是scrollview的圖例,可見srollview是一種滑動功能的控件,亦是非常常見的控件. 一般寫法如下: package com.mycompany.viewscroller; import ...

  2. 安卓中級教程(8):pathbutton中的animation.java研究(1)

    src/geniuz/myPathbutton/myAnimations.java package geniuz.myPathbutton; import java.util.ArrayList; i ...

  3. 安卓中級教程(10):@InjectView

    package com.example.android.db01; import android.app.Activity; import android.content.ContentValues; ...

  4. 安卓中級教程(5):ScrollView與refreshable之間的設置

    設置向下拉動更新. package com.mycompany.Scroll_test; import android.app.*; import android.os.*; import andro ...

  5. 安卓中級教程(4):ScrollView與ListView之間的高度問題

    在scrollView中加插ListView是一個大難題.其中一個難題是Listview的高度難以計算,輸出效果往往強差人意,就讓我們看看當中的問題 . <LinearLayout xmlns: ...

  6. 安卓中級教程(6):annotation的基本用法

    package com.example.ele_me.activity; import android.annotation.SuppressLint; import android.app.Acti ...

  7. 安卓中級教程(1):@InjectView

    package com.mycompany.hungry; import android.annotation.SuppressLint; import android.app.Activity; i ...

  8. 安卓中級教程(11):深入研究餓了麼的各個java檔運作關係(1)

    package com.example.ele_me.activity; import android.annotation.SuppressLint; import android.app.Acti ...

  9. 安卓中級教程(7):annotation中的 public @interface的用法

    package com.example.ele_me.util; import java.lang.annotation.Retention; import java.lang.annotation. ...

随机推荐

  1. ngCloak 实现 Angular 初始化闪烁最佳实践

    在做angular的SPA开发时,我们经常会遇见在如Chrome这类能够快速解析的浏览器上出现表达式({{ express }} ),或者是模块(div)的闪烁.对于这个问题由于JavaScript去 ...

  2. 交叉编译fftw

    交叉编译 fftw 使用的源码是 fftw-3.2.2-arm.tar.gz 新塘平台arm ./configure --prefix=/usr/local/fftw_arm --host=arm-l ...

  3. 百度地图SDK

      百度地图官方SDK文档 http://lbsyun.baidu.com/index.php?title=androidsdk   一.申请百度地图SDK 每一个app对应一个百度地图AK,百度地图 ...

  4. SoapUI 设置 request data with json body

    --背景 使用WCF定义REST风格的WebService,如下: [ServiceContract]    public interface INISTService    {        [Op ...

  5. js函数中this的不同含义

    1.js函数调用过程中,js线程会进入新的执行环境并创建该环境的变量对象,并添加两个变量:this和arguments,因此可以在函数中使用这两个变量.需要注意的是,this变量不能重新赋值,而arg ...

  6. linux启动和关闭

    startup,startup mount,startup nomount之间的区别: STARTUP NOMOUNT选项:(读初始化参数文件,启动实例)STARTUP NOMOUNT选项启动实例,但 ...

  7. C#动态创建和动态使用程序集、类、方法、字段等

    C#动态创建和动态使用程序集.类.方法.字段等 分类:技术交流 (3204)  (3)   首先需要知道动态创建这些类型是使用的一些什么技术呢?其实只要相关动态加载程序集呀,类呀,都是使用反射,那么动 ...

  8. GNU/Linux下LVM配置管理以及快照卷、物理卷、卷组、逻辑卷的创建和删除

    LVM是Linux环境中对磁盘分区进行管理的一种机制,是建立在硬盘和分区之上.文件系统之下的一个逻辑层,可提高磁盘分区管理的灵活性.最大的优点是在不损伤数据的前提下调整存储空间的大小. 本篇主要讲述L ...

  9. 日志解析LogParse启动参数配置

    -task task_stat1001to1010.yaml -log log4j_stat1001to1010.xml 用绝对路径

  10. Vim基础操作

    在正式使用Vim之前,先来点开胃菜,学习下Vim中一些常用的命令,有了这些基本命令,才能让我们使用Vim更加得心应手,加快工作的效率~ 注意:接下来将要介绍的命令主要是用在Vim的Normal模式下. ...