編輯:關於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>
效果: 代碼:https://github.com/ldb-github/Layout_Tab1、布局:使用LinearLayout布置標簽;再使用FrameL
一、安裝及配置Genymotion(1)由於Eclipse中自帶的SDK模擬器,啟動之慢,不說了 現在給大家介紹一種比較快的模擬器Genymotion(2)首先去Geny
像QQ,微博,360等手機應用大部分的應用啟動的一個頁面都是顯示自己產品的logo,不但可以打下廣告還可以掩飾後台加載的行為,今天在自己的應用加上了這個功能,簡單的記錄總
Android ADB 用法adb 全稱是 Android Debug Bridge, 就是起到調試橋的作用。 用來操作android設備的閱讀目錄 adb