-
onMeasure & onLayout查看全部
-
測(cè)試和完善 1.添加一個(gè)ListView,在滾動(dòng)ListView時(shí)如果菜單是打開(kāi)的,那么將菜單將閉合 mListView.setOnScrollListener(new AbsListView.OnScrollListener() { public void onScroll(……) { if (mArcMenuLeftBottom.isOpen()){ mArcMenuLeftBottom.toggleMenu(600); } } }); 這個(gè)isOpen函數(shù)用來(lái)判斷當(dāng)前菜單是否是打開(kāi)的 2.為菜單項(xiàng)添加點(diǎn)擊相應(yīng)事件 mArcMenuRightBottom.setOnMenuItemClickListener(new ArcMenu.OnMenuItemClickListener() { public void onClick(View view, int pos) { Toast.makeText(MainActivity.this, ""+view.getTag(), Toast.LENGTH_SHORT).show(); } }); 3.優(yōu)化布局文件 (1)將ArcMenu的布局重新放入一個(gè)新的布局xml中,可以指定其位置 <com.zhangxt4.satellitemenu.view.ArcMenu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:zhangxt4="http://schemas.android.com/apk/res-auto" android:id="@+id/id_menu_left_bottom" zhangxt4:position="left_bottom" zhangxt4:radius="150dp"> 注意添加命名空間 (2)在主布局中直接include就行了 <include layout="@layout/menu_left_bottom" ></include> 注意ArcMenu的先后順序,后面的會(huì)覆蓋前面的,所以要把ArcMenu放到后面。查看全部
-
監(jiān)聽(tīng)item點(diǎn)擊事件——設(shè)置點(diǎn)擊動(dòng)畫 1.實(shí)現(xiàn)目標(biāo): 當(dāng)菜單展開(kāi)后,點(diǎn)擊某個(gè)子菜單,它會(huì)變大消失,其他菜單項(xiàng)會(huì)縮小消失 這個(gè)處理應(yīng)該是toggleMenu的for循環(huán)中實(shí)現(xiàn),因?yàn)槊總€(gè)子菜單都具備這樣的功能。 思路: 當(dāng)點(diǎn)擊某個(gè)菜單項(xiàng)時(shí),會(huì)遍歷每個(gè)子菜單,根據(jù)pos參數(shù)來(lái)判斷,被點(diǎn)擊了就會(huì)放大,其他縮小。 2.步驟如下: final int pos = i+1; childView.setOnClickListener(new OnClickListener() { public void onClick(View v) { if(mMenuItemClickListener != null) { //設(shè)置點(diǎn)擊事件 mMenuItemClickListener.onClick(childView, pos); } //設(shè)置點(diǎn)擊后的動(dòng)畫,即被點(diǎn)擊者放大消失,其他菜單縮小消失 menuItemAnim(pos); //更新菜單閉合/展開(kāi)狀態(tài),如果當(dāng)前是open的,點(diǎn)擊后應(yīng)該是close changeStatus(); } }); 3.點(diǎn)擊某個(gè)子菜單后的動(dòng)畫效果: (1)遍歷所有的子菜單View,如果是被點(diǎn)擊的菜單item,就放大消失,其他縮小消失 (2)最后點(diǎn)擊后的動(dòng)畫效果完畢后,所有的子View都不能點(diǎn)擊和聚焦了 private void menuItemAnim(int pos) { for(int i = 1; i<getChildCount(); i++) { View childView = getChildAt(i); if (i == pos) { childView.startAnimation(scaleBigAnim(300)); } else { childView.startAnimation(scaleSmallAnim(300)); } childView.setClickable(false); childView.setFocusable(false); } } 4.被點(diǎn)擊菜單項(xiàng)會(huì)出現(xiàn)放大消失兩個(gè)動(dòng)畫效果(如圖) 5.其他菜單項(xiàng)會(huì)出現(xiàn)縮小消失兩個(gè)動(dòng)畫效果(同上)查看全部
-
展開(kāi)item——結(jié)尾 1.最后需要設(shè)置一個(gè)移出的先后順序,效果像是依次展開(kāi)每個(gè)子菜單 tranAnim.setStartOffset((i*100)/count); 2.兩個(gè)小注意點(diǎn): (1)改變菜單展開(kāi)/閉合狀態(tài)的時(shí)間應(yīng)該在for循環(huán)之外 (2)正確設(shè)置兩個(gè)動(dòng)畫的先后順序 animSet.addAnimation(rotateAnim); animSet.addAnimation(tranAnim);查看全部
-
展開(kāi)item——子菜單的展開(kāi)/閉合 1.在明確實(shí)現(xiàn)目標(biāo)之后,在for循環(huán)中實(shí)現(xiàn)每個(gè)子View的平移和旋轉(zhuǎn)動(dòng)畫效果 public void toggleMenu(int duration) { for (int i = 0; i < count-1; i++){ childView.setVisibility(View.VISIBLE); //起始應(yīng)該是顯示的 (1)創(chuàng)建一個(gè)AnimationSet來(lái)包含這兩個(gè)動(dòng)畫 AnimationSet animSet = new AnimationSet(true); (2)平移動(dòng)畫 1)為子菜單項(xiàng)平移動(dòng)畫設(shè)置開(kāi)始和結(jié)束位置 當(dāng)ViewGroup在左邊時(shí),start位置相對(duì)于end是左移的,即(-cl) 當(dāng)ViewGroup在頂部時(shí),start位置相對(duì)于end是上移的,即(-ct) 2)根據(jù)當(dāng)前狀態(tài)來(lái)設(shè)置動(dòng)畫 if (Status.CLOSE){//to open tranAnim = new TranslateAnimation(cl*xflag, 0, ct*yflag, 0); }else {//to close tranAnim = new TranslateAnimation(0, cl*xflag, 0, ct*yflag); } 3)為動(dòng)畫設(shè)置一個(gè)監(jiān)聽(tīng),設(shè)置動(dòng)畫結(jié)束后子View的顯示/消失 if (Status.CLOSE){ childView.setVisibility(View.GONE); } (2)旋轉(zhuǎn)動(dòng)畫 RotateAnimation rotateAnim = new RotateAnimation(0, 720f, ……); (3)為子菜單view設(shè)置這兩個(gè)動(dòng)畫 animSet.addAnimation(rotateAnim); animSet.addAnimation(tranAnim); childView.startAnimation(animSet); } (4)最后在for循環(huán)之后更新一下?tīng)顟B(tài) changeStatus();//mCurrentStatus = (mCurrentStatus == Status.CLOSE?Status.OPEN:Status.CLOSE); }查看全部
-
展開(kāi)item 1.首先要明確目標(biāo): 點(diǎn)擊主按鈕時(shí),主按鈕有一個(gè)旋轉(zhuǎn)動(dòng)畫;同時(shí)子菜單項(xiàng)會(huì)展開(kāi),每個(gè)子菜單項(xiàng)有一個(gè)平移動(dòng)畫和一個(gè)旋轉(zhuǎn)動(dòng)畫。 所以整個(gè)效果都會(huì)在主按鈕的onClick()中實(shí)現(xiàn) 2.主按鈕的旋轉(zhuǎn)動(dòng)畫 (1)onClick() public void onClick(View v) { rotateCButton(v, 0f, 360f, 300); //將主按鈕旋轉(zhuǎn)動(dòng)畫專門放在一個(gè)函數(shù)中處理 …… } (2)rotateCButton() private void rotateCButton(View v, float start, float end, int duration) { //1. 創(chuàng)建一個(gè)旋轉(zhuǎn)動(dòng)畫,指定起始和結(jié)束角度,以及旋轉(zhuǎn)中心點(diǎn) //旋轉(zhuǎn)中心是以自己為中心,0.5f表示自己View的一半 RotateAnimation anim = new RotateAnimation(start, end, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); //2. 設(shè)置旋轉(zhuǎn)時(shí)間,并指定在旋轉(zhuǎn)后就固定住不動(dòng)了 anim.setDuration(duration); anim.setFillAfter(true); //3. 為主按鈕view設(shè)置這個(gè)動(dòng)畫 v.startAnimation(anim); } 3.展開(kāi)/關(guān)閉子菜單時(shí)的動(dòng)畫 實(shí)現(xiàn)目標(biāo): (1)子菜單View本身就是存在于最終顯示位置的,只是閉合時(shí)設(shè)置為GONE了 (2)點(diǎn)擊主按鈕時(shí),每個(gè)子菜單View會(huì)從主按鈕的位置平移到顯示位置,同時(shí)伴隨有旋轉(zhuǎn)動(dòng)畫 (3)這些子菜單View旋轉(zhuǎn)出來(lái)有一點(diǎn)點(diǎn)先后順序 這里就需要有一個(gè)toggleMenu()的方法,根據(jù)當(dāng)前菜單的閉合/展開(kāi)狀態(tài)來(lái)顯示不同的動(dòng)畫效果,并更新?tīng)顟B(tài) 接下來(lái)單獨(dú)拉出來(lái)一個(gè)筆記來(lái)說(shuō)查看全部
-
定位item(定位每個(gè)子菜單的位置) (2)這是一個(gè)復(fù)雜的過(guò)程,首先通過(guò)圖算出子菜單View的相對(duì)于父容器左邊和頂部的寬和高,實(shí)際上就是對(duì)應(yīng)layout(int l, int t, int r, int b)的l和t這兩個(gè)參數(shù) 但是要注意由于菜單位置不同,l和t的計(jì)算值會(huì)不同 //逐個(gè)定位每個(gè)子菜單View的位置 for (int i = 0; i < count - 1; i++){ View child = getChildAt(i+1); //因?yàn)橹靼粹o是0,所以子菜單從1開(kāi)始到count-1 int cl = (int) (mRadius * Math.sin(Math.PI/2/(count-2)*i)); //注意第一個(gè)子菜單的sin角度為0 int ct = (int) (mRadius * Math.cos(Math.PI/2/(count-2)*i)); //每個(gè)子菜單View本身的寬和高 int cWidth = child.getMeasuredWidth(); int cHeight = child.getMeasuredHeight(); //如果菜單位于底部(左下,右下),相對(duì)于頂部的參數(shù)ct就需要調(diào)整 if (mPosition == Position.LEFT_BOTTOM || mPosition == Position.RIGHT_BOTTOM){ ct = getMeasuredHeight() - cHeight - ct; } //如果菜單位于右部(右下,右上),相對(duì)于左邊的參數(shù)cl就需要調(diào)整 if (mPosition == Position.RIGHT_BOTTOM || mPosition == Position.RIGHT_TOP){ cl = getMeasuredWidth() - cWidth - cl; } child.layout(cl, ct, cl+cWidth, ct+cHeight); }查看全部
-
重寫onMeasure()和onLayout() 1.要測(cè)量和定位自定義控件(ViewGroup)中的所有子View,就需要重寫這兩個(gè)方法 2.首先需要在layout布局中定義ArcMenu這個(gè)ViewGroup中的所有子View(child)(略) 注意: (1)第一個(gè)child View就是主按鈕,即getChildAt(0)。它也是由兩個(gè)圖片合成的RelativeLayout (2)每個(gè)子菜單對(duì)應(yīng)的View是一個(gè)ImageView,當(dāng)然這里也可以定義成一個(gè)包裹ImageView的RelativeLayout 3.onMeasure()完成所有子View的測(cè)量 (如圖) 4.onLayout()完成所有子View的定位 (1)定位主按鈕 private void layoutCButton() { mCButton = getChildAt(0); //第一個(gè)子View就是主按鈕 //定位一個(gè)view需要使用ViewGroup的layout(int l, int t, int r, int b)方法 四個(gè)參數(shù)分別為相對(duì)父容器的left,top,right和bottom 下面是根據(jù)主按鈕的位置來(lái)確定這四個(gè)參數(shù)值 int l = 0, t = 0; //默認(rèn) int width = mCButton.getMeasuredWidth(); //獲取主按鈕的寬 int height = mCButton.getMeasuredHeight(); //獲取主按鈕的高 switch (mPosition){ case LEFT_TOP: case LEFT_BOTTOM: t = getMeasuredHeight() - height; //在下邊時(shí),t=ViewGroup的高-主按鈕的高 case RIGHT_TOP: l = getMeasuredWidth() - width; //在右邊時(shí),l=ViewGroup的寬-主按鈕的寬 case RIGHT_BOTTOM: 同上; } mCButton.layout(l, t, l+width, t+height); //傳入四個(gè)參數(shù)來(lái)定位主按鈕 } (2)定位子菜單的View(下一筆記)查看全部
-
自定義屬性 2)在ArcMenu構(gòu)造函數(shù)中獲取屬性值 TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ArcMenu, defStyleAttr, 0); int position = ta.getInt(R.styleable.ArcMenu_position, POS_RIGHT_BOTTOM); //獲取在layout布局中指定的位置屬性,默認(rèn)是右下 mRadius = (int) ta.getDimension(R.styleable.ArcMenu_radius, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics())); //獲取在layout布局中指定的半徑屬性值,默認(rèn)是100dp;第二個(gè)參數(shù)是將100dp轉(zhuǎn)換成像素值 3.為子菜單項(xiàng)設(shè)置點(diǎn)擊回調(diào)接口 public interface OnMenuItemClickListener { //聲明要實(shí)現(xiàn)的接口方法 void onClick(View view, int pos); } private OnMenuItemClickListener mMenuItemClickListener; //設(shè)置回調(diào)的接口 public void SetOnMenuItemClickListener(OnMenuItemClickListener mListener) { this.mMenuItemClickListener = mListener; }查看全部
-
自定義屬性 1.定義兩個(gè)自定義屬性:主按鈕位置、子菜單半徑 2.自定義屬性的使用步驟: (1)在attr.xml中定義這兩個(gè)屬性 <resources> <attr name="position" > <enum name="left_top" value="0" /> <enum name="left_bottom" value="1" /> <enum name="right_top" value="2" /> <enum name="right_bottom" value="3" /> </attr> <attr name="radius" format="dimension" /> <declare-styleable name="ArcMenu"> <attr name="position" /> <attr name="radius" /> </declare-styleable> (2)在layout中使用 注意在AS中需要按如下添加命名空間 xmlns:zhangxt4="http://schemas.android.com/apk/res-auto" //添加命名空間 <com.zhangxt4.satellitemenu.view.ArcMenu zhangxt4:position="right_bottom" zhangxt4:radius="150dp"> (3)在自定義控件中讀取layout中指定的屬性值 自定義控件為public class ArcMenu extends ViewGroup { 1)首先定義連個(gè)變量用來(lái)表示前面的兩個(gè)屬性 //菜單位置的枚舉類 public enum Position { LEFT_TOP, LEFT_BOTTOM, RIGHT_TOP, RIGHT_BOTTOM } private Position mPosition = Position.RIGHT_BOTTOM; //默認(rèn)是右下方 private int mRadius; //子菜單的半徑 2)在ArcMenu構(gòu)造函數(shù)中獲取屬性值(如圖) 根據(jù)獲取的屬性值來(lái)設(shè)置主按鈕位置和半徑 3.為子菜單項(xiàng)設(shè)置回調(diào)點(diǎn)擊事件查看全部
-
功能介紹 1.要完成的工作 (1)這是一個(gè)自定義控件,其位置屬性可以是四個(gè)角的任何位置 (2)彈出子菜單的時(shí)候會(huì)有一些動(dòng)畫效果 (3)子菜單的位置本來(lái)就在(剛開(kāi)始隱藏了),點(diǎn)擊主按鈕時(shí)會(huì)出現(xiàn),同時(shí)伴隨動(dòng)畫效果 (4)子菜單的位置要經(jīng)過(guò)數(shù)學(xué)知識(shí)來(lái)計(jì)算得到查看全部
-
layout(左,上,右,下)原點(diǎn)是以屏幕的左上角查看全部
-
ScaleAnimation的構(gòu)造函數(shù),最難理解的應(yīng)該就是:int pivotXType, float pivotXValue, int pivotYType, float pivotYValue。 pivotXType和pivotXValue指的就是放大和縮小的中心點(diǎn)。選擇Animation.RELATIVE_TO_SELF和0.5f就是以自己為標(biāo)準(zhǔn),x軸的中心。查看全部
-
講的不錯(cuò)。查看全部
-
自定義ViewGroup查看全部
舉報(bào)
0/150
提交
取消