国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android仿QQ6.0主頁面側滑效果

2019-12-12 04:50:07
字體:
來源:轉載
供稿:網友

1.概述

  最近一直都在帶實習生做項目,發現自己好久沒有寫博客了,這幾天更新會比較頻繁,今天玩QQ的時候發現QQ主頁菜單滑動效果早就變了,實在忍不住晚上就來實現一下了!

2.實現 

  2.1. 實現的方式多種多樣
  2.1.1 自定義ViewGroup ,處理其onTouch事件
  2.1.2 FrameLayout + 手勢處理類GestureDetector
  2.2.3 使用Google自帶的DrawerLayout 對其進行修改
  2.2.4 繼承自水平滾動HorizontalScrollView
大家可以看一下這個http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/0909/6612.html,這種方式繼承自ViewGroup,個人覺得還行但是還是比較繁瑣要處理的東西也比較多,那么我就用最后一種2.2.4的方式實現,有人說直接去網上下載一個源代碼就可以了,這我就只能GG了。

  2.3. 自定義SlidingMenu extends HorizontalScrollView 然后寫好布局文件這個和ScrollView的用法一樣,只不過是橫向滾動的

/** * description: * 仿QQ5.0主頁面側滑的自定View * Created by 曾輝 on 2016/11/1. * QQ:240336124 * Email: 240336124@qq.com * Version:1.0 */public class SlidingMenu extends HorizontalScrollView { public SlidingMenu(Context context) { super(context); } public SlidingMenu(Context context, AttributeSet attrs) { super(context, attrs); } public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }}

2.4. 運行起來之后發現布局不對,完全亂了明明都是match_parent可是就是不行那么我們就需要用代碼指定菜單和內容的寬度:

菜單的寬度 = 屏幕的寬度 - 自定義的右邊留出的寬度
內容的寬度 = 屏幕的寬度

/** * description: * 仿QQ5.0主頁面側滑的自定View * Created by 曾輝 on 2016/11/1. * QQ:240336124 * Email: 240336124@qq.com * Version:1.0 */public class SlidingMenu extends HorizontalScrollView { private View mMenuView; private View mContentView; private int mMenuWidth; public SlidingMenu(Context context) { this(context, null); } public SlidingMenu(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // 獲取自定義的右邊留出的寬度 TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.SlidingMenu); float rightPadding = array.getDimension(  R.styleable.SlidingMenu_rightPadding,dip2px(50)); // 計算菜單的寬度 = 屏幕的寬度 - 自定義右邊留出的寬度 mMenuWidth = (int) (getScreenWidth() - rightPadding); array.recycle(); } /** * 把dip 轉成像素 */ private float dip2px(int dip) { return TypedValue.applyDimension(  TypedValue.COMPLEX_UNIT_DIP,dip,getResources().getDisplayMetrics()); } @Override protected void onFinishInflate() { super.onFinishInflate(); // 1.獲取根View也就是外層的LinearLayout ViewGroup container = (ViewGroup) this.getChildAt(0); int containerChildCount = container.getChildCount(); if(containerChildCount>2){  // 里面只允許放置兩個布局 一個是Menu(菜單布局) 一個是Content(主頁內容布局)  throw new IllegalStateException("SlidingMenu 根布局LinearLayout下面只允許兩個布局,菜單布局和主頁內容布局"); } // 2.獲取菜單和內容布局 mMenuView = container.getChildAt(0); mContentView = container.getChildAt(1); // 3.指定內容和菜單布局的寬度 // 3.1 菜單的寬度 = 屏幕的寬度 - 自定義的右邊留出的寬度 mMenuView.getLayoutParams().width = mMenuWidth; // 3.2 內容的寬度 = 屏幕的寬度 mContentView.getLayoutParams().width = getScreenWidth(); } /** * 獲取屏幕的寬度 */ public int getScreenWidth() { Resources resources = this.getResources(); DisplayMetrics dm = resources.getDisplayMetrics(); return dm.widthPixels; }}

目前的效果就是可以滑動,并且菜單和主頁面內容的布局寬度正常

  2.5 接下來一開始就讓菜單滑動到關閉狀態,手指滑動抬起判斷菜單打開和關閉并做相應的處理 onLayout() onTouch() smoothScrollTo(),當手指快速的時候切換菜單的狀態利用GestureDetector 手勢處理類:

 /** * description: * 仿QQ5.0主頁面側滑的自定View * Created by 曾輝 on 2016/11/1. * QQ:240336124 * Email: 240336124@qq.com * Version:1.0 */public class SlidingMenu extends HorizontalScrollView { private View mMenuView; private View mContentView; private int mMenuWidth; // 手勢處理類 主要用來處理手勢快速滑動 private GestureDetector mGestureDetector; // 菜單是否打開 private boolean mMenuIsOpen = false; public SlidingMenu(Context context) { this(context, null); } public SlidingMenu(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // 獲取自定義的右邊留出的寬度 TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); float rightPadding = array.getDimension(  R.styleable.SlidingMenu_rightPadding, dip2px(50)); // 計算菜單的寬度 = 屏幕的寬度 - 自定義右邊留出的寬度 mMenuWidth = (int) (getScreenWidth() - rightPadding); array.recycle(); // 實例化手勢處理類 mGestureDetector = new GestureDetector(context,new GestureListener()); } /** * 把dip 轉成像素 */ private float dip2px(int dip) { return TypedValue.applyDimension(  TypedValue.COMPLEX_UNIT_DIP, dip, getResources().getDisplayMetrics()); } @Override protected void onFinishInflate() { super.onFinishInflate(); // 1.獲取根View也就是外層的LinearLayout ViewGroup container = (ViewGroup) this.getChildAt(0); int containerChildCount = container.getChildCount(); if (containerChildCount > 2) {  // 里面只允許放置兩個布局 一個是Menu(菜單布局) 一個是Content(主頁內容布局)  throw new IllegalStateException("SlidingMenu 根布局LinearLayout下面只允許兩個布局,菜單布局和主頁內容布局"); } // 2.獲取菜單和內容布局 mMenuView = container.getChildAt(0); mContentView = container.getChildAt(1); // 3.指定內容和菜單布局的寬度 // 3.1 菜單的寬度 = 屏幕的寬度 - 自定義的右邊留出的寬度 mMenuView.getLayoutParams().width = mMenuWidth; // 3.2 內容的寬度 = 屏幕的寬度 mContentView.getLayoutParams().width = getScreenWidth(); } @Override public boolean onTouchEvent(MotionEvent ev) { // 處理手指快速滑動 if(mGestureDetector.onTouchEvent(ev)){  return mGestureDetector.onTouchEvent(ev); } switch (ev.getAction()) {  case MotionEvent.ACTION_UP:  // 手指抬起獲取滾動的位置  int currentScrollX = getScrollX();  if (currentScrollX > mMenuWidth / 2) {   // 關閉菜單   closeMenu();  } else {   // 打開菜單   openMenu();  }  return false; } return super.onTouchEvent(ev); } /** * 打開菜單 */ private void openMenu() { smoothScrollTo(0, 0); mMenuIsOpen = true; } /** * 關閉菜單 */ private void closeMenu() { smoothScrollTo(mMenuWidth, 0); mMenuIsOpen = false; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); // 布局指定后會從新擺放子布局,當其擺放完畢后,讓菜單滾動到不可見狀態 if (changed) {  scrollTo(mMenuWidth, 0); } } /** * 獲取屏幕的寬度 */ public int getScreenWidth() { Resources resources = this.getResources(); DisplayMetrics dm = resources.getDisplayMetrics(); return dm.widthPixels; } private class GestureListener extends GestureDetector.SimpleOnGestureListener{ @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {  // 當手指快速滑動時候回調的方法  Log.e("TAG",velocityX+"");  // 如果菜單打開 并且是向左快速滑動 切換菜單的狀態  if(mMenuIsOpen){  if(velocityX<-500){   toggleMenu();   return true;  }  }else{  // 如果菜單關閉 并且是向右快速滑動 切換菜單的狀態  if(velocityX>500){   toggleMenu();   return true;  }  }  return false; } } /** * 切換菜單的狀態 */ private void toggleMenu() { if(mMenuIsOpen){  closeMenu(); }else{  openMenu(); } }}

到了這一步之后我們就可以切換菜單了,并且處理了手指快速滑動,迫不及待的看下效果

2.6. 實現菜單左邊抽屜樣式的動畫效果,監聽滾動回調的方法onScrollChanged() 這個就非常簡單了一句話就搞定,效果就不看了一起看終極效果吧

@Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); // l 是 當前滾動的x距離 在滾動的時候會不斷反復的回調這個方法 Log.e(TAG,l+""); mMenuView.setTranslationX(l*0.8f); }

2.7. 實現菜單右邊菜單的陰影透明度效果,這個打算在主頁面內容布局上面加一層陰影,用ImageView即可,那么我們的內容View就需要換了

/** * description: * 仿QQ5.0主頁面側滑的自定View * Created by 曾輝 on 2016/11/1. * QQ:240336124 * Email: 240336124@qq.com * Version:1.0 */public class SlidingMenu extends HorizontalScrollView { private static final String TAG = "HorizontalScrollView"; private Context mContext; // 4.給菜單和內容View指定寬高 - 左邊菜單View private View mMenuView; // 4.給菜單和內容View指定寬高 - 菜單的寬度 private int mMenuWidth; // 5.3 手勢處理類 主要用來處理手勢快速滑動 private GestureDetector mGestureDetector; // 5.3 菜單是否打開 private boolean mMenuIsOpen = false; // 7(4). 主頁面內容View的布局包括陰影ImageView private ViewGroup mContentView; // 7.給內容添加陰影效果 - 陰影的ImageView private ImageView mShadowIv; public SlidingMenu(Context context) { this(context, null); } public SlidingMenu(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //4.1 計算左邊菜單的寬度 //4.1.1 獲取自定義的右邊留出的寬度 TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu); float rightPadding = array.getDimension(  R.styleable.SlidingMenu_rightPadding, dip2px(50)); // 4.1.2 計算菜單的寬度 = 屏幕的寬度 - 自定義右邊留出的寬度 mMenuWidth = (int) (getScreenWidth() - rightPadding); array.recycle(); // 5.3 實例化手勢處理類 mGestureDetector = new GestureDetector(context,new GestureListener()); this.mContext = context; } /** * 把dip 轉成像素 */ private float dip2px(int dip) { return TypedValue.applyDimension(  TypedValue.COMPLEX_UNIT_DIP, dip, getResources().getDisplayMetrics()); } @Override protected void onFinishInflate() { super.onFinishInflate(); // 4.2 指定菜單和內容View的寬度 // 4.2.1.獲取根View也就是外層的LinearLayout ViewGroup container = (ViewGroup) this.getChildAt(0); int containerChildCount = container.getChildCount(); if (containerChildCount > 2) {  // 里面只允許放置兩個布局 一個是Menu(菜單布局) 一個是Content(主頁內容布局)  throw new IllegalStateException("SlidingMenu 根布局LinearLayout下面只允許兩個布局,菜單布局和主頁內容布局"); } // 4.2.2.獲取菜單和內容布局 mMenuView = container.getChildAt(0); // 7.給內容添加陰影效果 // 7.1 先new一個主內容布局用來放 陰影和LinearLayout原來的內容布局 mContentView = new FrameLayout(mContext); ViewGroup.LayoutParams contentParams = new ViewGroup.LayoutParams(  ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT); // 7.2 獲取原來的內容布局,并把原來的內容布局從LinearLayout中異常 View oldContentView = container.getChildAt(1); container.removeView(oldContentView); // 7.3 把原來的內容View 和 陰影加到我們新創建的內容布局中 mContentView.addView(oldContentView); // 7.3.1 創建陰影ImageView mShadowIv = new ImageView(mContext); mShadowIv.setBackgroundColor(Color.parseColor("#99000000")); mContentView.addView(mShadowIv); // 7.4 把包含陰影的新的內容View 添加到 LinearLayout中 container.addView(mContentView); // 4.2.3.指定內容和菜單布局的寬度 // 4.2.3.1 菜單的寬度 = 屏幕的寬度 - 自定義的右邊留出的寬度 mMenuView.getLayoutParams().width = mMenuWidth; // 4.2.3.2 內容的寬度 = 屏幕的寬度 mContentView.getLayoutParams().width = getScreenWidth(); } /** * 5.處理手指抬起和快速滑動切換菜單 */ @Override public boolean onTouchEvent(MotionEvent ev) { // 5.3 處理手指快速滑動 if(mGestureDetector.onTouchEvent(ev)){  return mGestureDetector.onTouchEvent(ev); } switch (ev.getAction()) {  case MotionEvent.ACTION_UP:  // 5.1 手指抬起獲取滾動的位置  int currentScrollX = getScrollX();  if (currentScrollX > mMenuWidth / 2) {   // 5.1.1 關閉菜單   closeMenu();  } else {   // 5.1.2 打開菜單   openMenu();  }  return false; } return super.onTouchEvent(ev); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); // l 是 當前滾動的x距離 在滾動的時候會不斷反復的回調這個方法 Log.e(TAG,l+""); // 6. 實現菜單左邊抽屜樣式的動畫效果 mMenuView.setTranslationX(l*0.8f); // 7.給內容添加陰影效果 - 計算梯度值 float gradientValue = l * 1f / mMenuWidth;// 這是 1 - 0 變化的值 // 7.給內容添加陰影效果 - 給陰影的View指定透明度 0 - 1 變化的值 float shadowAlpha = 1 - gradientValue; mShadowIv.setAlpha(shadowAlpha); } /** * 5.1.2 打開菜單 */ private void openMenu() { smoothScrollTo(0, 0); mMenuIsOpen = true; } /** * 5.1.1 關閉菜單 */ private void closeMenu() { smoothScrollTo(mMenuWidth, 0); mMenuIsOpen = false; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); // 布局指定后會從新擺放子布局,當其擺放完畢后,讓菜單滾動到不可見狀態 if (changed) {  scrollTo(mMenuWidth, 0); } } /** * 獲取屏幕的寬度 */ public int getScreenWidth() { Resources resources = this.getResources(); DisplayMetrics dm = resources.getDisplayMetrics(); return dm.widthPixels; } /** * 5.3 處理手指快速滑動 */ private class GestureListener extends GestureDetector.SimpleOnGestureListener{ @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {  // 當手指快速滑動時候回調的方法  Log.e(TAG,velocityX+"");  // 5.3.1 如果菜單打開 并且是向左快速滑動 切換菜單的狀態  if(mMenuIsOpen){  if(velocityX<0){   toggleMenu();   return true;  }  }else{  // 5.3.2 如果菜單關閉 并且是向右快速滑動 切換菜單的狀態  if(velocityX>0){   toggleMenu();   return true;  }  }  return false; } } /** * 切換菜單的狀態 */ private void toggleMenu() { if(mMenuIsOpen){  closeMenu(); }else{  openMenu(); } }}

我們來看一下最后的效果吧,最終代碼量不是很多啦,需要的請下載源碼,如果是實現QQ5.0或是酷狗的側滑效果可以自己改改。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 长海县| 凤山市| 阿拉善盟| 芜湖市| 铁岭县| 遵义市| 靖安县| 安溪县| 汉寿县| 固原市| 盐亭县| 饶阳县| 灵台县| 齐齐哈尔市| 芒康县| 曲水县| 扶风县| 中江县| 利津县| 乐东| 皮山县| 红原县| 壶关县| 淄博市| 同心县| 玉树县| 上思县| 青龙| 兴和县| 南开区| 琼海市| 轮台县| 临安市| 岐山县| 泰兴市| 辛集市| 安达市| 女性| 商都县| 和田县| 鸡东县|