Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android 實現從左邊滑動出來的抽屜

Android 實現從左邊滑動出來的抽屜

編輯:Android開發實例

應該就是傳說中的手機人人客戶端的實現方法了吧

主要是老外蛋疼的代碼 改了一下

 

需要自定義view

 

 

  1. <?xml version="1.0" encoding="utf-8"?> 
  2.  
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  4.  
  5. xmlns:panel="http://schemas.android.com/apk/res/com.su.houses"//和包名一致!  
  6.  
  7. android:layout_width="fill_parent" 
  8.  
  9. android:layout_height="fill_parent" 
  10.  
  11. android:background="#FFFFFFFF" 
  12.  
  13. android:orientation="horizontal" > 
  14.  
  15.  
  16. <com.su.houses.panel.Panel 
  17.  
  18. android:id="@+id/leftPanel1" 
  19.  
  20. android:layout_width="wrap_content" 
  21.  
  22. android:layout_height="fill_parent" 
  23.  
  24. panel:closedHandle="@xml/left_switcher_collapsed_background" 
  25.  
  26. panel:openedHandle="@xml/left_switcher_expanded_background" 
  27.  
  28. panel:position="left" > 
  29.  
  30.  
  31. <Button 
  32.  
  33. android:id="@+id/panelHandle" 
  34.  
  35. android:layout_width="10dip" 
  36.  
  37. android:layout_height="fill_parent" /> 
  38.  
  39.  
  40. <!-- 下面是抽屜的布局 --> 
  41.  
  42.  
  43. <LinearLayout 
  44.  
  45. android:id="@id/panelContent" 
  46.  
  47. android:layout_width="fill_parent" 
  48.  
  49. android:layout_height="fill_parent" 
  50.  
  51. android:background="#999932" 
  52.  
  53. android:gravity="center" 
  54.  
  55. android:orientation="vertical" > 
  56.  
  57.  
  58. <Button 
  59.  
  60. android:layout_width="wrap_content" 
  61.  
  62. android:layout_height="wrap_content" 
  63.  
  64. android:background="@drawable/button" 
  65.  
  66. android:text="項目介紹" /> 
  67.  
  68.  
  69. <Button 
  70.  
  71. android:layout_width="wrap_content" 
  72.  
  73. android:layout_height="wrap_content" 
  74.  
  75. android:background="@drawable/button" 
  76.  
  77. android:text="總體規劃" /> 
  78.  
  79.  
  80. <Button 
  81.  
  82. android:layout_width= "wrap_content" 
  83.  
  84. android:layout_height="wrap_content" 
  85.  
  86. android:background="@drawable/button" 
  87.  
  88. android:text="交通動線" 
  89.  
  90. wrap_content="" /> 
  91.  
  92.  
  93. <Button 
  94.  
  95. android:layout_width="wrap_content" 
  96.  
  97. android:layout_height="wrap_content" 
  98.  
  99. android:background="@drawable/button" 
  100.  
  101. android:text="生活配套" /> 
  102.  
  103.  
  104. <Button 
  105.  
  106. android:layout_width="wrap_content" 
  107.  
  108. android:layout_height="wrap_content" 
  109.  
  110. android:background="@drawable/button" 
  111.  
  112. android:text="未來生活" /> 
  113.  
  114. </LinearLayout> 
  115.  
  116. </com.su.houses.panel.Panel> 
  117.  
  118.  
  119. <ImageView 
  120.  
  121. android:id="@+id/project_image" 
  122.  
  123. android:layout_width="fill_parent" 
  124.  
  125. android:layout_height="fill_parent" 
  126.  
  127. android:src="@drawable/dogs" /> 
  128.  
  129.  
  130. </LinearLayout> 

Panel.java

 

  1. package com.su.houses.panel;  
  2.  
  3.  
  4.  
  5. import com.su.houses.R;  
  6.  
  7.  
  8. import android.content.Context;  
  9.  
  10. import android.content.res.TypedArray;  
  11.  
  12. import android.graphics.Canvas;  
  13.  
  14. import android.graphics.drawable.Drawable;  
  15.  
  16. import android.util.AttributeSet;  
  17.  
  18. import android.view.GestureDetector;  
  19.  
  20. import android.view.GestureDetector.OnGestureListener;  
  21.  
  22. import android.view.MotionEvent;  
  23.  
  24. import android.view.View;  
  25.  
  26. import android.view.animation.Animation;  
  27.  
  28. import android.view.animation.Animation.AnimationListener;  
  29.  
  30. import android.view.animation.Interpolator;  
  31.  
  32. import android.view.animation.LinearInterpolator;  
  33.  
  34. import android.view.animation.TranslateAnimation;  
  35.  
  36. import android.widget.LinearLayout;  
  37.  
  38.  
  39. public class Panel extends LinearLayout  
  40.  
  41. {  
  42.  
  43.  
  44. /**  
  45.  
  46. * Callback invoked when the panel is opened/closed.  
  47.  
  48. */ 
  49.  
  50. public static interface OnPanelListener  
  51.  
  52. {  
  53.  
  54. /**  
  55.  
  56. * Invoked when the panel becomes fully closed.  
  57.  
  58. */ 
  59.  
  60. public void onPanelClosed(Panel panel);  
  61.  
  62.  
  63. /**  
  64.  
  65. * Invoked when the panel becomes fully opened.  
  66.  
  67. */ 
  68.  
  69. public void onPanelOpened(Panel panel);  
  70.  
  71. }  
  72.  
  73.  
  74. private boolean mIsShrinking; // 判斷是否是正在收縮狀態  
  75.  
  76.  
  77. private int mPosition;  
  78.  
  79.  
  80. private int mDuration;  
  81.  
  82.  
  83. private boolean mLinearFlying;  
  84.  
  85.  
  86. private View mHandle;  
  87.  
  88.  
  89. private View mContent;  
  90.  
  91.  
  92. private Drawable mOpenedHandle;  
  93.  
  94.  
  95. private Drawable mClosedHandle;  
  96.  
  97.  
  98. private float mTrackX;// X方向上的隱藏追蹤  
  99.  
  100.  
  101. private float mTrackY;// Y方向上的隱藏跟蹤  
  102.  
  103.  
  104. private float mVelocity;// Fling狀態每秒鐘劃的像素。  
  105.  
  106.  
  107. private OnPanelListener panelListener;  
  108.  
  109.  
  110. public static final int TOP = 0;  
  111.  
  112.  
  113. public static final int BOTTOM = 1;  
  114.  
  115.  
  116. public static final int LEFT = 2;  
  117.  
  118.  
  119. public static final int RIGHT = 3;  
  120.  
  121.  
  122. private enum State  
  123.  
  124. {  
  125.  
  126. ABOUT_TO_ANIMATE, // 由READY進入這個狀態,但還沒有發生動畫,滾動,和滑動  
  127.  
  128. ANIMATING, // 正在動畫  
  129.  
  130. READY, // 就緒狀態什麼都不做  
  131.  
  132. TRACKING, // 拖動  
  133.  
  134. FLYING,  
  135.  
  136. };  
  137.  
  138.  
  139. private State mState;  
  140.  
  141.  
  142. private Interpolator mInterpolator;  
  143.  
  144.  
  145. private GestureDetector mGestureDetector; // 手勢監聽器  
  146.  
  147.  
  148. private int mContentHeight;  
  149.  
  150.  
  151. private int mContentWidth;  
  152.  
  153.  
  154. private int mOrientation; // 這個方向是動畫出現的方向。可以修改mPositon來修改實驗一下  
  155.  
  156.  
  157. private PanelOnGestureListener mGestureListener; // 手勢監聽器的回調  
  158.  
  159.  
  160. public Panel(Context context, AttributeSet attrs)  
  161.  
  162. {  
  163.  
  164. super(context, attrs);  
  165.  
  166. TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Panel);  
  167.  
  168. mDuration = a.getInteger(R.styleable.Panel_animationDuration, 750); // duration defaults to 750 ms  
  169.  
  170. mPosition = a.getInteger(R.styleable.Panel_position, BOTTOM); // position defaults to BOTTOM  
  171.  
  172. mLinearFlying = a.getBoolean(R.styleable.Panel_linearFlying, false); // linearFlying defaults to false  
  173.  
  174. mOpenedHandle = a.getDrawable(R.styleable.Panel_openedHandle);  
  175.  
  176. mClosedHandle = a.getDrawable(R.styleable.Panel_closedHandle);  
  177.  
  178. a.recycle();  
  179.  
  180. mOrientation = (mPosition == TOP || mPosition == BOTTOM) ? VERTICAL : HORIZONTAL;  
  181.  
  182. setOrientation(mOrientation);  
  183.  
  184. mState = State.READY; // 記錄控件的各個狀態  
  185.  
  186. mGestureListener = new PanelOnGestureListener();  
  187.  
  188. mGestureDetector = new GestureDetector(mGestureListener);  
  189.  
  190. mGestureDetector.setIsLongpressEnabled(false);// 長按沒有返回值所以去掉  
  191.  
  192. }  
  193.  
  194.  
  195. /**  
  196.  
  197. * Sets the listener that receives a notification when the panel becomes open/close.  
  198.  
  199. *   
  200.  
  201. * @param onPanelListener The listener to be notified when the panel is opened/closed.  
  202.  
  203. */ 
  204.  
  205. public void setOnPanelListener(OnPanelListener onPanelListener)  
  206.  
  207. {  
  208.  
  209. panelListener = onPanelListener;  
  210.  
  211. }  
  212.  
  213.  
  214. /**  
  215.  
  216. * Gets Panel's mHandle  
  217.  
  218. *   
  219.  
  220. * @return Panel's mHandle  
  221.  
  222. */ 
  223.  
  224. public View getHandle()  
  225.  
  226. {  
  227.  
  228. return mHandle;  
  229.  
  230. }  
  231.  
  232.  
  233. /**  
  234.  
  235. * Gets Panel's mContent  
  236.  
  237. *   
  238.  
  239. * @return Panel's mContent  
  240.  
  241. */ 
  242.  
  243. public View getContent()  
  244.  
  245. {  
  246.  
  247. return mContent;  
  248.  
  249. }  
  250.  
  251.  
  252. /**  
  253.  
  254. * Sets the acceleration curve for panel's animation.  
  255.  
  256. *   
  257.  
  258. * @param i The interpolator which defines the acceleration curve  
  259.  
  260. */ 
  261.  
  262. public void setInterpolator(Interpolator i)  
  263.  
  264. {  
  265.  
  266. mInterpolator = i;  
  267.  
  268. }  
  269.  
  270.  
  271. /**  
  272.  
  273. * Set the opened state of Panel.  
  274.  
  275. *   
  276.  
  277. * @param open True if Panel is to be opened, false if Panel is to be closed.  
  278.  
  279. * @param animate True if use animation, false otherwise.  
  280.  
  281. *   
  282.  
  283. */ 
  284.  
  285. public void setOpen(boolean open, boolean animate)  
  286.  
  287. {  
  288.  
  289. if (isOpen() ^ open)  
  290.  
  291. {  
  292.  
  293. mIsShrinking = !open;  
  294.  
  295. if (animate)  
  296.  
  297. {  
  298.  
  299. mState = State.ABOUT_TO_ANIMATE;  
  300.  
  301. if (!mIsShrinking)  
  302.  
  303. {  
  304.  
  305. // this could make flicker so we test mState in dispatchDraw()  
  306.  
  307. // to see if is equal to ABOUT_TO_ANIMATE  
  308.  
  309. mContent.setVisibility(VISIBLE);  
  310.  
  311. }  
  312.  
  313. post(startAnimation);  
  314.  
  315. }  
  316.  
  317. else 
  318.  
  319. {  
  320.  
  321. mContent.setVisibility(open ? VISIBLE : GONE);  
  322.  
  323. postProcess();  
  324.  
  325. }  
  326.  
  327. }  
  328.  
  329. }  
  330.  
  331.  
  332. /**  
  333.  
  334. * Returns the opened status for Panel.  
  335.  
  336. *   
  337.  
  338. * @return True if Panel is opened, false otherwise.  
  339.  
  340. */ 
  341.  
  342. public boolean isOpen()  
  343.  
  344. {  
  345.  
  346. return mContent.getVisibility() == VISIBLE;  
  347.  
  348. }  
  349.  
  350.  
  351. /*  
  352.  
  353. * 在這裡完成了一些handler與Content的初始化工作  
  354.  
  355. */ 
  356.  
  357. @Override 
  358.  
  359. protected void onFinishInflate()  
  360.  
  361. {  
  362.  
  363. super.onFinishInflate(); // 調用超類方法  
  364.  
  365. mHandle = findViewById(R.id.panelHandle); // 獲取handle引用設置Handle的監聽器  
  366.  
  367. if (mHandle == null)  
  368.  
  369. {  
  370.  
  371. throw new RuntimeException("Your Panel must have a View whose id attribute is 'R.id.panelHandle'");  
  372.  
  373. }  
  374.  
  375. mHandle.setOnTouchListener(touchListener);  
  376.  
  377.  
  378. mContent = findViewById(R.id.panelContent); // 獲取Content的引用  
  379.  
  380. if (mContent == null)  
  381.  
  382. {  
  383.  
  384. throw new RuntimeException("Your Panel must have a View whose id attribute is 'R.id.panelContent'");  
  385.  
  386. }  
  387.  
  388.  
  389. // reposition children  
  390.  
  391. removeView(mHandle);  
  392.  
  393. removeView(mContent);  
  394.  
  395. if (mPosition == TOP || mPosition == LEFT)  
  396.  
  397. {  
  398.  
  399. addView(mContent);  
  400.  
  401. addView(mHandle);  
  402.  
  403. }  
  404.  
  405. else 
  406.  
  407. {  
  408.  
  409. addView(mHandle);  
  410.  
  411. addView(mContent);  
  412.  
  413. }  
  414.  
  415.  
  416. if (mClosedHandle != null) // 設置handle的背景  
  417.  
  418. {  
  419.  
  420. mHandle.setBackgroundDrawable(mClosedHandle);  
  421.  
  422. }  
  423.  
  424. mContent.setVisibility(GONE); // 隱藏內容  
  425.  
  426. }  
  427.  
  428.  
  429. /*  
  430.  
  431. * 主要是獲取了Content的寬高  
  432.  
  433. */ 
  434.  
  435. @Override 
  436.  
  437. protected void onLayout(boolean changed, int l, int t, int r, int b)  
  438.  
  439. {  
  440.  
  441. super.onLayout(changed, l, t, r, b);  
  442.  
  443. mContentWidth = mContent.getWidth();  
  444.  
  445. mContentHeight = mContent.getHeight();  
  446.  
  447. }  
  448.  
  449.  
  450. /*  
  451.  
  452. * 根據控件的不同的狀態修改畫布的偏移量  
  453.  
  454. */ 
  455.  
  456. @Override 
  457.  
  458. protected void dispatchDraw(Canvas canvas)  
  459.  
  460. {  
  461.  
  462. // String name = getResources().getResourceEntryName(getId());  
  463.  
  464. // this is why 'mState' was added:  
  465.  
  466. // avoid flicker before animation start  
  467.  
  468. if (mState == State.ABOUT_TO_ANIMATE && !mIsShrinking)  
  469.  
  470. {  
  471.  
  472. int delta = mOrientation == VERTICAL ? mContentHeight : mContentWidth;  
  473.  
  474. if (mPosition == LEFT || mPosition == TOP)  
  475.  
  476. {  
  477.  
  478. delta = -delta;  
  479.  
  480. }  
  481.  
  482. if (mOrientation == VERTICAL)  
  483.  
  484. {  
  485.  
  486. canvas.translate(0, delta);// translate(float,float)的作用。將控件的起始坐標平移到(0,delta)的位置  
  487.  
  488. }  
  489.  
  490. else 
  491.  
  492. {  
  493.  
  494. // 這裡平移到了delta,0的位置,但是等控件完全展開後如果還是這個矩陣的話,  
  495.  
  496. // 那Content應該是看不到,現在能 看到,那在哪裡轉化了呢。動畫完了就還原  
  497.  
  498. canvas.translate(delta, 0);  
  499.  
  500.  
  501. }  
  502.  
  503. }  
  504.  
  505. if (mState == State.TRACKING || mState == State.FLYING)  
  506.  
  507. {  
  508.  
  509. canvas.translate(mTrackX, mTrackY);  
  510.  
  511. /*  
  512.  
  513. * 激活狀態的Content和handler以mTranceX和mTranckY為參數不斷的移動就能形成動畫  
  514.  
  515. */ 
  516.  
  517. /*  
  518.  
  519. * 不會,translate只能使view看起來發生了變化,但layout(),不會被調用 也就是,外部的處罰事件還是會按照translate以前的標准觸發。  
  520.  
  521. */ 
  522.  
  523. /*  
  524.  
  525. * 沒什麼關系,translate不會改變框架中事件的判斷。  
  526.  
  527. */ 
  528.  
  529.  
  530. }  
  531.  
  532. super.dispatchDraw(canvas);  
  533.  
  534. }  
  535.  
  536.  
  537. private float ensureRange(float v, int min, int max)  
  538.  
  539. {  
  540.  
  541. v = Math.max(v, min);  
  542.  
  543. v = Math.min(v, max);  
  544.  
  545. return v;  
  546.  
  547. }  
  548.  
  549.  
  550. OnTouchListener touchListener = new OnTouchListener()  
  551.  
  552. {  
  553.  
  554. int initX;  
  555.  
  556.  
  557. int initY;  
  558.  
  559.  
  560. boolean setInitialPosition; // 判斷是否設置了初始滾動位置 它是類的成員函數  
  561.  
  562.  
  563. public boolean onTouch(View v, MotionEvent event)  
  564.  
  565. {  
  566.  
  567. int action = event.getAction();  
  568.  
  569. // if 用戶向下按  
  570.  
  571. // Content的X方向和Y方向滾動都為0  
  572.  
  573. // if 內容為隱藏狀態 根據方向和位置修改X方向或Y方向上的滾動  
  574.  
  575. if (action == MotionEvent.ACTION_DOWN)  
  576.  
  577. {  
  578.  
  579. initX = 0;  
  580.  
  581. initY = 0;  
  582.  
  583. if (mContent.getVisibility() == GONE)  
  584.  
  585. {  
  586.  
  587. // since we may not know content dimensions we use factors here  
  588.  
  589. if (mOrientation == VERTICAL)  
  590.  
  591. {  
  592.  
  593. initY = mPosition == TOP ? -1 : 1;  
  594.  
  595. }  
  596.  
  597. else 
  598.  
  599. {  
  600.  
  601. initX = mPosition == LEFT ? -1 : 1;  
  602.  
  603. }  
  604.  
  605. }  
  606.  
  607. // 設置初始化的記錄為true  
  608.  
  609. setInitialPosition = true;  
  610.  
  611. }  
  612.  
  613. else 
  614.  
  615. {  
  616.  
  617. // if 用戶按下的不是向下  
  618.  
  619. // if 已經設置了初始滾動位置  
  620.  
  621. // 修改內容X,Y方向上的滾動。  
  622.  
  623. // 設置控件滾動的初始化位置  
  624.  
  625. // 設置初始化的記錄為false  
  626.  
  627. /*  
  628.  
  629. * ACTION_DOWN的操作都是根據handle的,Content激活後重新layout,handle的位置發生了改變, 而以後所有的操作的坐標又都是根據現在的handler的位置的,這樣就存在了誤差  
  630.  
  631. * 所有需要offsetLocation把這個誤差修正過來。  
  632.  
  633. */ 
  634.  
  635. if (setInitialPosition)  
  636.  
  637. {  
  638.  
  639. // now we know content dimensions, so we multiply factors...  
  640.  
  641. initX *= mContentWidth;  
  642.  
  643. initY *= mContentHeight;  
  644.  
  645. // ... and set initial panel's position  
  646.  
  647. mGestureListener.setScroll(initX, initY);  
  648.  
  649. setInitialPosition = false;  
  650.  
  651. // for offsetLocation we have to invert values  
  652.  
  653. initX = -initX;  
  654.  
  655. initY = -initY;  
  656.  
  657. }  
  658.  
  659. // offset every ACTION_MOVE & ACTION_UP event  
  660.  
  661. // 如果這裡去掉,開始拖動不響應,拖動了一段距離後才能拉出Content  
  662.  
  663. event.offsetLocation(initX, initY); // 在X,Y的方向上分別加上initX,initY。  
  664.  
  665.  
  666. /*  
  667.  
  668. * 不加這一句會使distanceX的值差異非常大,而distanceX會影響到mTranceX。  
  669.  
  670. */ 
  671.  
  672.  
  673. /*  
  674.  
  675. * mTranceX是有范圍的,如果最小值小於這個范圍就不會在發生該變了, 所有 會出現延遲的現象。其實那是還沒有到達最小值。  
  676.  
  677. */ 
  678.  
  679. }  
  680.  
  681.  
  682. // if 手勢監聽器沒有處理  
  683.  
  684. // if 用戶事件為抬起事件 啟動動畫線程  
  685.  
  686. boolean result = mGestureDetector.onTouchEvent(event);  
  687.  
  688. if (!result)  
  689.  
  690. {  
  691.  
  692. if (action == MotionEvent.ACTION_UP)  
  693.  
  694. {  
  695.  
  696. // tup up after scrolling  
  697.  
  698. post(startAnimation);  
  699.  
  700. }  
  701.  
  702. }  
  703.  
  704. return false;  
  705.  
  706. }  
  707.  
  708. };  
  709.  
  710.  
  711. Runnable startAnimation = new Runnable()  
  712.  
  713. {  
  714.  
  715. public void run()  
  716.  
  717. {  
  718.  
  719. // this is why we post this Runnable couple of lines above:  
  720.  
  721. // now its save to use mContent.getHeight() && mContent.getWidth()  
  722.  
  723. TranslateAnimation animation; // 負責移動的動畫  
  724.  
  725. int fromXDelta = 0, toXDelta = 0, fromYDelta = 0, toYDelta = 0;// ???() 動畫的起始、終點坐標。相對於器parent View  
  726.  
  727. // if 控件狀態為Fling  
  728.  
  729. // 判斷是否處於收縮狀態  
  730.  
  731. if (mState == State.FLYING)  
  732.  
  733. {  
  734.  
  735. mIsShrinking = (mPosition == TOP || mPosition == LEFT) ^ (mVelocity > 0);  
  736.  
  737. }  
  738.  
  739. // if 控件為縱向  
  740.  
  741. // 獲取Y方向Delta  
  742.  
  743. // if 控件是拖動  
  744.  
  745. // 計算周期時間   
  746.  
  747.  
  748. int calculatedDuration;  
  749.  
  750. if (mOrientation == VERTICAL)  
  751.  
  752. {  
  753.  
  754. int height = mContentHeight;  
  755.  
  756. if (!mIsShrinking)  
  757.  
  758. {  
  759.  
  760. fromYDelta = mPosition == TOP ? -height : height;  
  761.  
  762. }  
  763.  
  764. else 
  765.  
  766. {  
  767.  
  768. toYDelta = mPosition == TOP ? -height : height;  
  769.  
  770. }  
  771.  
  772. if (mState == State.TRACKING)  
  773.  
  774. {  
  775.  
  776. if (Math.abs(mTrackY - fromYDelta) < Math.abs(mTrackY - toYDelta))  
  777.  
  778. {  
  779.  
  780. mIsShrinking = !mIsShrinking;  
  781.  
  782. toYDelta = fromYDelta;  
  783.  
  784. }  
  785.  
  786. fromYDelta = (int)mTrackY;  
  787.  
  788. }  
  789.  
  790. else if (mState == State.FLYING)  
  791.  
  792. {  
  793.  
  794. fromYDelta = (int)mTrackY;  
  795.  
  796. }  
  797.  
  798. // for FLYING events we calculate animation duration based on flying velocity  
  799.  
  800. // also for very high velocity make sure duration >= 20 ms  
  801.  
  802. if (mState == State.FLYING && mLinearFlying)  
  803.  
  804. {  
  805.  
  806. calculatedDuration = (int)(1000 * Math.abs((toYDelta - fromYDelta) / mVelocity));  
  807.  
  808. calculatedDuration = Math.max(calculatedDuration, 20);  
  809.  
  810. }  
  811.  
  812. else 
  813.  
  814. {  
  815.  
  816. calculatedDuration = mDuration * Math.abs(toYDelta - fromYDelta) / mContentHeight;  
  817.  
  818. }  
  819.  
  820. }  
  821.  
  822. else 
  823.  
  824. {  
  825.  
  826. int width = mContentWidth;  
  827.  
  828. if (!mIsShrinking)  
  829.  
  830. {  
  831.  
  832. fromXDelta = mPosition == LEFT ? -width : width;  
  833.  
  834. }  
  835.  
  836. else 
  837.  
  838. {  
  839.  
  840. toXDelta = mPosition == LEFT ? -width : width;  
  841.  
  842. }  
  843.  
  844. if (mState == State.TRACKING)  
  845.  
  846. {  
  847.  
  848. if (Math.abs(mTrackX - fromXDelta) < Math.abs(mTrackX - toXDelta))  
  849.  
  850. {  
  851.  
  852. mIsShrinking = !mIsShrinking;  
  853.  
  854. toXDelta = fromXDelta;  
  855.  
  856. }  
  857.  
  858. fromXDelta = (int)mTrackX;  
  859.  
  860. }  
  861.  
  862. else if (mState == State.FLYING)  
  863.  
  864. {  
  865.  
  866. fromXDelta = (int)mTrackX;  
  867.  
  868. }  
  869.  
  870. // for FLYING events we calculate animation duration based on flying velocity  
  871.  
  872. // also for very high velocity make sure duration >= 20 ms  
  873.  
  874. if (mState == State.FLYING && mLinearFlying)  
  875.  
  876. {  
  877.  
  878. calculatedDuration = (int)(1000 * Math.abs((toXDelta - fromXDelta) / mVelocity));  
  879.  
  880. calculatedDuration = Math.max(calculatedDuration, 20);  
  881.  
  882. }  
  883.  
  884. else 
  885.  
  886. {  
  887.  
  888. calculatedDuration = mDuration * Math.abs(toXDelta - fromXDelta) / mContentWidth;  
  889.  
  890. }  
  891.  
  892. }  
  893.  
  894.  
  895. mTrackX = mTrackY = 0;  
  896.  
  897. // if 計算周期為0  
  898.  
  899. // toXDelta跟fromXDelta相等  
  900.  
  901. if (calculatedDuration == 0)  
  902.  
  903. {  
  904.  
  905. mState = State.READY;  
  906.  
  907. if (mIsShrinking)  
  908.  
  909. {  
  910.  
  911. mContent.setVisibility(GONE);  
  912.  
  913. }  
  914.  
  915. postProcess();  
  916.  
  917. return;  
  918.  
  919. }  
  920.  
  921.  
  922.  
  923. animation = new TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);  
  924.  
  925. animation.setDuration(calculatedDuration);  
  926.  
  927. animation.setAnimationListener(animationListener);  
  928.  
  929. if (mState == State.FLYING && mLinearFlying)  
  930.  
  931. {  
  932.  
  933. animation.setInterpolator(new LinearInterpolator());  
  934.  
  935. }  
  936.  
  937. else if (mInterpolator != null)  
  938.  
  939. {  
  940.  
  941. animation.setInterpolator(mInterpolator);  
  942.  
  943. }  
  944.  
  945. startAnimation(animation);  
  946.  
  947. }  
  948.  
  949. };  
  950.  
  951.  
  952.  
  953. private AnimationListener animationListener = new AnimationListener()  
  954.  
  955. {  
  956.  
  957. public void onAnimationEnd(Animation animation)  
  958.  
  959. {  
  960.  
  961. mState = State.READY;  
  962.  
  963. if (mIsShrinking)  
  964.  
  965. {  
  966.  
  967. mContent.setVisibility(GONE);  
  968.  
  969. }  
  970.  
  971. postProcess();  
  972.  
  973. }  
  974.  
  975.  
  976. public void onAnimationRepeat(Animation animation)  
  977.  
  978. {  
  979.  
  980. }  
  981.  
  982.  
  983. public void onAnimationStart(Animation animation)  
  984.  
  985. {  
  986.  
  987. mState = State.ANIMATING;  
  988.  
  989. }  
  990.  
  991. };  
  992.  
  993.  
  994. /**  
  995.  
  996. * 處理背景的drawable  
  997.  
  998. */ 
  999.  
  1000. private void postProcess()  
  1001.  
  1002. {  
  1003.  
  1004. if (mIsShrinking && mClosedHandle != null)  
  1005.  
  1006. {  
  1007.  
  1008. mHandle.setBackgroundDrawable(mClosedHandle);  
  1009.  
  1010. }  
  1011.  
  1012. else if (!mIsShrinking && mOpenedHandle != null)  
  1013.  
  1014. {  
  1015.  
  1016. mHandle.setBackgroundDrawable(mOpenedHandle);  
  1017.  
  1018. }  
  1019.  
  1020. // invoke listener if any  
  1021.  
  1022. if (panelListener != null)  
  1023.  
  1024. {  
  1025.  
  1026. if (mIsShrinking)  
  1027.  
  1028. {  
  1029.  
  1030. panelListener.onPanelClosed(Panel.this);  
  1031.  
  1032. }  
  1033.  
  1034. else 
  1035.  
  1036. {  
  1037.  
  1038. panelListener.onPanelOpened(Panel.this);  
  1039.  
  1040. }  
  1041.  
  1042. }  
  1043.  
  1044. }  
  1045.  
  1046.  
  1047. class PanelOnGestureListener implements OnGestureListener  
  1048.  
  1049. {  
  1050.  
  1051. float scrollY;  
  1052.  
  1053.  
  1054. float scrollX;  
  1055.  
  1056.  
  1057. public void setScroll(int initScrollX, int initScrollY)  
  1058.  
  1059. {  
  1060.  
  1061. scrollX = initScrollX;  
  1062.  
  1063. scrollY = initScrollY;  
  1064.  
  1065. }  
  1066.  
  1067.  
  1068. public boolean onDown(MotionEvent e)  
  1069.  
  1070. {  
  1071.  
  1072. scrollX = scrollY = 0;  
  1073.  
  1074. if (mState != State.READY)  
  1075.  
  1076. {  
  1077.  
  1078. // we are animating or just about to animate  
  1079.  
  1080. return false;  
  1081.  
  1082. }  
  1083.  
  1084. mState = State.ABOUT_TO_ANIMATE;  
  1085.  
  1086. mIsShrinking = mContent.getVisibility() == VISIBLE;  
  1087.  
  1088. if (!mIsShrinking)  
  1089.  
  1090. {  
  1091.  
  1092. // this could make flicker so we test mState in dispatchDraw()  
  1093.  
  1094. // to see if is equal to ABOUT_TO_ANIMATE  
  1095.  
  1096. mContent.setVisibility(VISIBLE);  
  1097.  
  1098. }  
  1099.  
  1100. return true;  
  1101.  
  1102. }  
  1103.  
  1104.  
  1105. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)  
  1106.  
  1107. {  
  1108.  
  1109. mState = State.FLYING;  
  1110.  
  1111. mVelocity = mOrientation == VERTICAL ? velocityY : velocityX;  
  1112.  
  1113. post(startAnimation);  
  1114.  
  1115. return true;  
  1116.  
  1117. }  
  1118.  
  1119.  
  1120. public void onLongPress(MotionEvent e)  
  1121.  
  1122. {  
  1123.  
  1124.  
  1125. }  
  1126.  
  1127.  
  1128. /*  
  1129.  
  1130. * 該變mTranceX和mTranceY,更新UI  
  1131.  
  1132. */ 
  1133.  
  1134. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)  
  1135.  
  1136. {  
  1137.  
  1138. mState = State.TRACKING;  
  1139.  
  1140. float tmpY = 0, tmpX = 0;  
  1141.  
  1142. if (mOrientation == VERTICAL)  
  1143.  
  1144. {  
  1145.  
  1146. scrollY -= distanceY;  
  1147.  
  1148. if (mPosition == TOP)  
  1149.  
  1150. {  
  1151.  
  1152. tmpY = ensureRange(scrollY, -mContentHeight, 0);  
  1153.  
  1154. }  
  1155.  
  1156. else 
  1157.  
  1158. {  
  1159.  
  1160. tmpY = ensureRange(scrollY, 0, mContentHeight);  
  1161.  
  1162. }  
  1163.  
  1164. }  
  1165.  
  1166. else 
  1167.  
  1168. {  
  1169.  
  1170. scrollX -= distanceX;  
  1171.  
  1172. if (mPosition == LEFT)  
  1173.  
  1174. {  
  1175.  
  1176. tmpX = ensureRange(scrollX, -mContentWidth, 0);  
  1177.  
  1178. }  
  1179.  
  1180. else 
  1181.  
  1182. {  
  1183.  
  1184. tmpX = ensureRange(scrollX, 0, mContentWidth);  
  1185.  
  1186. }  
  1187.  
  1188. }  
  1189.  
  1190. if (tmpX != mTrackX || tmpY != mTrackY)  
  1191.  
  1192. {  
  1193.  
  1194. mTrackX = tmpX;  
  1195.  
  1196. mTrackY = tmpY;  
  1197.  
  1198. invalidate();  
  1199.  
  1200. }  
  1201.  
  1202. return true;  
  1203.  
  1204. }  
  1205.  
  1206.  
  1207. public void onShowPress(MotionEvent e)  
  1208.  
  1209. {  
  1210.  
  1211.  
  1212. }  
  1213.  
  1214.  
  1215. public boolean onSingleTapUp(MotionEvent e)  
  1216.  
  1217. {  
  1218.  
  1219. // simple tap: click  
  1220.  
  1221. post(startAnimation);  
  1222.  
  1223. return true;  
  1224.  
  1225. }  
  1226.  
  1227. }  
  1228.  
  1229. }  
   

left_switcher_collapsed_background.xml 一個 selector 沒什麼好說的  
  1. <selector xmlns:android="http://schemas.android.com/apk/res/android"> 
  2. <item android:state_window_focused="false" android:state_pressed="false" android:drawable="@drawable/notes_button" /> 
  3. <item android:state_window_focused="true" android:state_pressed="true" android:drawable="@drawable/notes_button" /> 
  4. <item android:state_focused="true" android:drawable="@drawable/notes_button" /> 
  5. </selector> 
    attrs.xml 配置抽屜的各種組件 放到valuse 文件夾下  
  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <resources> 
  3. <declare-styleable name="Panel"> 
  4. <!-- Defines panel animation duration in ms. --> 
  5. <attr format="integer" name="animationDuration" /> 
  6. <!-- Defines panel position on the screen. --> 
  7. <attr name="position"> 
  8. <!-- Panel placed at top of the screen. --> 
  9. <enum name="top" value="0" /> 
  10. <!-- Panel placed at bottom of the screen. --> 
  11. <enum name="bottom" value="1" /> 
  12. <!-- Panel placed at left of the screen. --> 
  13. <enum name="left" value="2" /> 
  14. <!-- Panel placed at right of the screen. --> 
  15. <enum name="right" value="3" /> 
  16. </attr> 
  17. <!-- Defines if flying gesture forces linear interpolator in animation. --> 
  18. <attr format="boolean" name="linearFlying" /> 
  19. <!-- Defines opened handle (drawable/color). --> 
  20. <attr format="reference|color" name="openedHandle" /> 
  21. <!-- Defines closed handle (drawable/color). --> 
  22. <attr format="reference|color" name="closedHandle" /> 
  23. </declare-styleable> 
  24. <declare-styleable name="SmoothButton"> 
  25. <attr format="reference" name="transitionDrawable" /> 
  26. <attr format="integer" name="transitionDrawableLength" /> 
  27. <attr format="color" name="transitionTextColorUp" /> 
  28. <attr format="color" name="transitionTextColorDown" /> 
  29. </declare-styleable> 
  30. <item name="panelHandle" type="id"/> 
  31. <item name="panelContent" type="id"/> 
  32. </resources> 
 

 

 

   

android界面實用代碼 總結

 
  1. 1.要想讓您的控件水平居中或垂直居中其實很簡單,只要在控件的上一級中 android:gravity="center" 
  2.  
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  4. android:orientation="vertical" 
  5. android:gravity="center"   
  6. android:background="#000000" 
  7. android:layout_width="fill_parent" 
  8. android:layout_height="fill_parent" 
  9. <ImageView 
  10. android:id="@+id/logo" 
  11. android:src="@drawable/logo" 
  12. android:layout_width="wrap_content" 
  13. android:layout_height="wrap_content" 
  14. /> 
  15.  
  16.  
  17. </LinearLayout> 

 

 

2.全局全屏

 

 

  1. <application 
  2.  
  3. android:icon="@drawable/ic_launcher" 
  4.  
  5. android:label="@string/app_name"   
  6.  
  7. android:theme="@android:style/Theme.NoTitleBar.Fullscreen"   
  8.  
  9. android:screenOrientation="landscape"   
  10.  

3.橫屏

 

 

  1. <activity 
  2.  
  3. android:label="@string/app_name" 
  4.  
  5. android:name=".HousesActivity"   
  6.  
  7. android:screenOrientation="landscape"> 

 

 
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved