日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【右滑返回】滑动冲突 Scroller DecorView

發布時間:2023/12/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【右滑返回】滑动冲突 Scroller DecorView 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

基本思想

我們的滑動邏輯主要是利用View的scrollBy() 方法, scrollTo()方法和Scroller類來實現的當手指拖動視圖的時候,我們監聽手指在屏幕上滑動的距離利用View的scrollBy() 方法使得View隨著手指的滑動而滑動而當手指離開屏幕,我們在根據邏輯使用Scroller類startScroll()方法設置滑動的參數,然后再根據View的scrollTo進行滾動。
對于View的滑動,存在一些Touch事件消費的處理等問題,最主要的就是Activity里面有一些ListView、 GridView、ScrollView等控件假如我們Activity里面存在ListView、GridView等控件的話,我們對Activity的最外層布局進行滾動根本就無效果,因為Touch事件被ListView、GridView等控件消費了,所以Activity的最外層布局根本得不到Touch事件,也就實現不了Touch邏輯了為了解決此Touch事件問題,我們將OnTouchListener直接設置到ListView、GridView上面,這樣子就避免了Activity的最外層接受不到Touch事件的問題了

核心:一個自定義View

public?class?SwipeBackLayout?extends?FrameLayout?{????//常量????/**手指向右滑動時的最小【滑動】距離(只有滑動超過此距離才滾動view)*/????public?static?int?X_MIN_DISTANCE_IF_MOVE?=?8;????/**手指向右滑動時的最大【起始】距離(防止誤操作,只有從左邊緣滑動才有效),這個值最好大于上面的值*/????public?static?int?X_MIN_START_DISTANCE?=?10;????/**手指向右滑動時的最小【滑動】距離(防止誤操作,只有滑動超過一定距離才關閉)*/????public?static?int?X_MIN_DISTANCE_FROM_LEFT?=?90;????/**自動滾動到左側(回到初始位置)消耗的時間*/????public?static?final?int?TIME_MOVE_TO_LEFT?=?20;????/**自動滾動到右側(關閉應用前)消耗的時間*/????public?static?final?int?TIME_MOVE_TO_RIGHT?=?200;
????//一些可以設置的成員????/**滑動時左邊緣是否顯示陰影*/????private?boolean?isShowShadow?=?true;????/**當touch位置有ViewPager,但是ViewPager不是在item0時,是否攔截【從屏幕邊緣down】的滑動事件*/????private?boolean?isInterceptWhenTouchViewPagerIfNotFirst?=?false;????/**滑動時左邊緣添加陰影*/????private?Drawable?mShadowDrawable?=?getResources().getDrawable(R.drawable.shadow_left);
????//臨時變量????/**是否要finish掉Activity*/????private?boolean?isFinish;????private?Activity?mActivity;????/**記錄按下時的觸摸點、移動時的觸摸點在屏幕上的X坐標*/????private?int?downX,?touchX;????private?Scroller?mScroller?=?new?Scroller(getContext());????private?List<ViewPager>?mViewPagers?=?new?LinkedList<ViewPager>();
????public?SwipeBackLayout(Context?context)?{????????this(context,?null);????}????public?SwipeBackLayout(Context?context,?AttributeSet?attrs)?{????????this(context,?attrs,?0);????}????public?SwipeBackLayout(Context?context,?AttributeSet?attrs,?int?defStyle)?{????????super(context,?attrs,?defStyle);????????DisplayMetrics?metric?=?new?DisplayMetrics();????????((WindowManager)?context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(metric);????????X_MIN_DISTANCE_FROM_LEFT?=?(int)?(metric.widthPixels?*?0.2f);//屏幕寬的1/5????????//滑動的時候,手的移動大于這個距離才開始移動控件;如果小于這個距離就不觸發移動控件。ViewPage就是用這個距離來判斷用戶是否翻頁的????????X_MIN_DISTANCE_IF_MOVE?=?ViewConfiguration.get(context).getScaledTouchSlop();????????Log.i("bqt",?X_MIN_DISTANCE_FROM_LEFT?+?"---"?+?X_MIN_DISTANCE_IF_MOVE);//144-16????????X_MIN_START_DISTANCE?=?X_MIN_DISTANCE_IF_MOVE?+?2;//這個值最好大于X_MIN_DISTANCE_IF_MOVE????}????//必須手動調用的方法????public?void?attachToActivityAndAsRootLayout(Activity?activity)?{????????mActivity?=?activity;????????FrameLayout?decorView?=?(FrameLayout)?activity.getWindow().getDecorView();//所有窗口的根View????????ViewGroup?decorChild?=?(ViewGroup)?decorView.getChildAt(0);//封裝內容區域和ActionBar區域的容器????????decorView.removeView(decorChild);? ? ? ??this.addView(decorChild);????????decorView.addView(this);????}????//******************************************************************************************????@Override????public?boolean?onInterceptTouchEvent(MotionEvent?event)?{????????if?(!isInterceptWhenTouchViewPagerIfNotFirst)?{????????????ViewPager?mViewPager?=?getMyTouchViewPager(mViewPagers,?event);????????????//如果存在ViewPager并且ViewPager不是處在第一個Item,我們才攔截Touch事件,否則不攔截(Touch事件由ViewPager處理)????????????if?(mViewPager?!=?null?&&?mViewPager.getCurrentItem()?!=?0)?return?super.onInterceptTouchEvent(event);????????}????????switch?(event.getActionMasked())?{????????case?MotionEvent.ACTION_DOWN:????????????downX?=?(int)?event.getRawX();//getRawX獲取的是相對父View(也即整個屏幕左上角)的位置坐標????????????touchX?=?downX;????????????break;????????case?MotionEvent.ACTION_MOVE:????????????if?(downX?<=?X_MIN_START_DISTANCE?//不是從屏幕左邊緣開始的不攔截????????????????????&&?event.getRawX()?-?downX?>?X_MIN_DISTANCE_IF_MOVE)?return?true;//滑動距離太小時暫不攔截????????????break;????????}????????return?super.onInterceptTouchEvent(event);????}????@Override????public?boolean?onTouchEvent(MotionEvent?event)?{????????switch?(event.getActionMasked())?{????????case?MotionEvent.ACTION_MOVE:????????????if?(event.getRawX()?-?downX?>?X_MIN_DISTANCE_IF_MOVE)?scrollBy(touchX?-?(int)?event.getRawX(),?0);//將View中的內容滾動指定距離????????????touchX?=?(int)?event.getRawX();????????????break;????????case?MotionEvent.ACTION_UP:????????????if?(Math.abs(getScrollX())?>=?X_MIN_DISTANCE_FROM_LEFT)?scrollRightOrLeft(true);//當滑動的距離大于我們設定的最小距離時,滑到右側????????????else?scrollRightOrLeft(false);//當滑動的距離小于我們設定的最小距離時,回到起始位置????????????break;????????}????????return?true;????}????@Override????protected?void?onLayout(boolean?changed,?int?l,?int?t,?int?r,?int?b)?{????????super.onLayout(changed,?l,?t,?r,?b);????????if?(changed)?getAlLViewPager(mViewPagers,?this);//【遞歸】遍歷整個View樹,獲取里面的ViewPager的集合????}????@Override????protected?void?dispatchDraw(Canvas?canvas)?{//調用View.onDraw為繪制VIew本身,調用dispatchDraw為繪制自己的孩子????????//Called?by?draw?to?draw?the?child?views.?This?may?be?overridden?by?derived?classes?to?gain?control?just?before?its?children?are?drawn?????????super.dispatchDraw(canvas);????????if?(isShowShadow?&&?mShadowDrawable?!=?null)?{????????????int?left?=?getLeft()?-?mShadowDrawable.getIntrinsicWidth();????????????int?right?=?left?+?mShadowDrawable.getIntrinsicWidth();????????????mShadowDrawable.setBounds(left,?getTop(),?right,?getBottom());????????????mShadowDrawable.draw(canvas);????????}????}????@Override????public?void?computeScroll()?{????????if?(mScroller.computeScrollOffset())?{????????????scrollTo(mScroller.getCurrX(),?mScroller.getCurrY());????????????postInvalidate();????????????if?(mScroller.isFinished()?&&?isFinish)?mActivity.finish();????????}????}????//******************************************************************************************????/**?????*?【遞歸】遍歷整個View樹,獲取里面的ViewPager的集合?????*/????private?void?getAlLViewPager(List<ViewPager>?mViewPagers,?ViewGroup?parent)?{????????int?childCount?=?parent.getChildCount();????????for?(int?i?=?0;?i?<?childCount;?i++)?{????????????View?child?=?parent.getChildAt(i);????????????if?(child?instanceof?ViewPager)?mViewPagers.add((ViewPager)?child);????????????else?if?(child?instanceof?ViewGroup)?getAlLViewPager(mViewPagers,?(ViewGroup)?child);????????}????}????/**?????*?返回我們touch范圍內的那個ViewPager?????*/????private?ViewPager?getMyTouchViewPager(List<ViewPager>?mViewPagers,?MotionEvent?ev)?{????????if?(mViewPagers?==?null?||?mViewPagers.size()?==?0)?return?null;????????Rect?mRect?=?new?Rect();????????for?(ViewPager?viewPager?:?mViewPagers)?{????????????viewPager.getHitRect(mRect);????????????if?(mRect.contains((int)?ev.getX(),?(int)?ev.getY()))?return?viewPager;????????}????????return?null;????}????/**?????*?滾動出界面或滾動到起始位置?????*/????private?void?scrollRightOrLeft(boolean?toRight)?{????????isFinish?=?toRight;????????if?(toRight)?mScroller.startScroll(getScrollX(),?0,?-getWidth()?-?getScrollX(),?0,?TIME_MOVE_TO_RIGHT);????????else?mScroller.startScroll(getScrollX(),?0,?-getScrollX(),?0,?TIME_MOVE_TO_LEFT);//int?startX,?int?startY,?int?dx,?int?dy,?int?duration????????postInvalidate();//刷新界面????}????//get和set方法******************************************************************************************????public?boolean?isInterceptWhenTouchViewPagerIfNotFirst()?{????????return?isInterceptWhenTouchViewPagerIfNotFirst;????}????public?void?setInterceptWhenTouchViewPagerIfNotFirst(boolean?isInterceptWhenTouchViewPagerIfNotFirst)?{????????this.isInterceptWhenTouchViewPagerIfNotFirst?=?isInterceptWhenTouchViewPagerIfNotFirst;????}????public?Drawable?getmShadowDrawable()?{????????return?mShadowDrawable;????}????public?void?setmShadowDrawable(Drawable?mShadowDrawable)?{????????this.mShadowDrawable?=?mShadowDrawable;????}????public?boolean?isShowShadow()?{????????return?isShowShadow;????}????public?void?setShowShadow(boolean?isShowShadow)?{????????this.isShowShadow?=?isShowShadow;????}}

Activity基類

/**?*?想要實現向右滑動刪除Activity效果只需要繼承SwipeBackActivity即可?*/public?class?SwipeBackActivity?extends?Activity?{????protected?SwipeBackLayout?rootLayout;????@Override????protected?void?onCreate(Bundle?savedInstanceState)?{????????requestWindowFeature(Window.FEATURE_NO_TITLE);//可以放在super.onCreate之后,但必須放在attachToActivityAndAsRootLayout之前????????super.onCreate(savedInstanceState);????????rootLayout?=?new?SwipeBackLayout(this);????????rootLayout.attachToActivityAndAsRootLayout(this);????}????@Override????public?void?startActivity(Intent?intent)?{????????super.startActivity(intent);????????overridePendingTransition(R.anim.base_slide_right_in,?R.anim.base_slide_remain);????}????@Override????public?void?onBackPressed()?{????????super.onBackPressed();????????overridePendingTransition(0,?R.anim.base_slide_right_out);????}????@Override????public?void?finish()?{????????super.finish();????????overridePendingTransition(0,?R.anim.base_slide_right_out);????}}

MainActivity

public?class?MainActivity?extends?ListActivity?{????protected?void?onCreate(Bundle?savedInstanceState)?{????????requestWindowFeature(Window.FEATURE_NO_TITLE);????????super.onCreate(savedInstanceState);????????String[]?array?=?{?"普通的Activity",?//????????????????"普通的Activity:不顯示陰影",//????????????????"普通的Activity:自定義陰影",?//????????????????"普通的Activity:背景透明",//????????????????"普通的Activity:Translucent主題",//????????????????"普通的Activity:Holo_Light主題",//????????????????"有ListView的Activity",?//????????????????"當touch位置有ViewPager,但ViewPager不是在item0時,不攔截滑動事件",//????????????????"當touch位置有ViewPager,即使ViewPager不是在item0時,也攔截【從屏幕邊緣down】的滑動事件"?};//我感覺這種方式的用戶體驗更好????????setListAdapter(new?ArrayAdapter<String>(this,?android.R.layout.simple_list_item_1,?new?ArrayList<String>(Arrays.asList(array))));????}????@Override????protected?void?onListItemClick(ListView?l,?View?v,?int?position,?long?id)?{????????if?(position?<=?5)?{????????????Intent?intent?=?new?Intent(this,?NormalActivity.class);????????????intent.putExtra("position",?position);????????????startActivity(intent);????????}?else?if?(position?==?6)?startActivity(new?Intent(MainActivity.this,?ListViewActivity.class));????????else?{????????????Intent?intent?=?new?Intent(this,?ViewPagerActivity.class);????????????intent.putExtra("position",?position);????????????startActivity(intent);????????}????????overridePendingTransition(R.anim.base_slide_right_in,?R.anim.base_slide_remain);????}}

NormalActivity

public?class?NormalActivity?extends?SwipeBackActivity?{????@Override????protected?void?onCreate(Bundle?savedInstanceState)?{????????//如果子類要requestWindowFeature,必須放在super.onCreate之前,因為父類SwipeBackActivity的onCreate方法已經獲取到了DecorView????????//也即子類在調用super.onCreate后,其窗口裝飾風格(即相應的根布局文件)已經確定好了(默認的),如:是否有標題、是否有icon等。????????//由于要求窗口裝飾風格一經確定就不能再修改,否則直接拋異常!而requestWindowFeature的作用就是根據你的設置選擇匹配的窗口裝飾風格????????//所以requestWindowFeature必須在包括setContentView以及getWindow().getDecorView()等行為之前調用!????????//注意:以上規則只適合requestWindowFeature等方法,全屏設置可以放在【任何】位置,比如在點擊某個View后調用也是可以的????????requestWindowFeature(Window.FEATURE_LEFT_ICON);//實際上這行代碼沒任何意義,因為會被super.onCreate中的設置覆蓋掉????????super.onCreate(savedInstanceState);????????TextView?tv_info?=?new?TextView(this);????????tv_info.setTextColor(Color.BLACK);????????tv_info.setTextSize(TypedValue.COMPLEX_UNIT_SP,?25);????????tv_info.setBackgroundColor(Color.RED);//必須設置背景色,否則是透明的????????tv_info.setGravity(Gravity.CENTER);????????switch?(getIntent().getIntExtra("position",?0))?{????????case?0:????????????tv_info.setText("默認顯示指定的陰影\n對于普通的Activity,不必一定要在屏幕邊緣開始滑才能退出");????????????break;????????case?1:????????????tv_info.setText("不顯示陰影");????????????rootLayout.setShowShadow(false);????????????break;????????case?2:????????????tv_info.setText("自定義陰影");????????????rootLayout.setmShadowDrawable(getResources().getDrawable(R.drawable.ic_launcher));????????????break;????????case?3:????????????tv_info.setText("背景透明");????????????tv_info.setBackgroundColor(Color.TRANSPARENT);????????????break;????????case?4:????????????tv_info.setText("Translucent主題");????????????new?AlertDialog.Builder(this).setTitle("Translucent主題").create().show();????????????break;????????case?5:????????????tv_info.setText("Holo_Light主題");????????????setTheme(android.R.style.Theme_Holo_Light);????????????new?AlertDialog.Builder(this).setTitle("Holo_Light主題").create().show();????????????break;????????}????????setContentView(tv_info);????}}

ListViewActivity

public?class?ListViewActivity?extends?SwipeBackActivity?{????@Override????protected?void?onCreate(Bundle?savedInstanceState)?{????????super.onCreate(savedInstanceState);????????List<String>?list?=?new?ArrayList<String>();????????for?(int?i?=?0;?i?<=?30;?i++)?{????????????list.add("包含ListView時不會有手勢沖突");????????}????????ListView?mListView?=?new?ListView(this);????????mListView.setBackgroundColor(Color.GREEN);//設置背景色????????mListView.setAdapter(new?ArrayAdapter<String>(ListViewActivity.this,?android.R.layout.simple_list_item_1,?list));????????setContentView(mListView);????}}

ViewPagerActivity

public?class?ViewPagerActivity?extends?SwipeBackActivity?{????private?List<View>?list?=?new?ArrayList<View>();????@Override????protected?void?onCreate(Bundle?savedInstanceState)?{????????super.onCreate(savedInstanceState);????????ViewPager?viewPager?=?new?ViewPager(this);????????for?(int?i?=?0;?i?<?5;?i++)?{????????????TextView?tv_info?=?new?TextView(this);????????????tv_info.setTextColor(Color.RED);????????????tv_info.setTextSize(TypedValue.COMPLEX_UNIT_SP,?300);????????????tv_info.setBackgroundColor(Color.GREEN);//必須設置背景色,否則是透明的????????????tv_info.setGravity(Gravity.CENTER);????????????tv_info.setText(""?+?i);????????????list.add(tv_info);????????}????????viewPager.setAdapter(new?Adapter(this,?list));????????setContentView(viewPager);????????if?(getIntent().getIntExtra("position",?0)?==?8)?rootLayout.setInterceptWhenTouchViewPagerIfNotFirst(true);????}????public?class?Adapter?extends?PagerAdapter?{????????private?List<View>?list;????????public?Adapter(Context?context,?List<View>?list)?{????????????this.list?=?list;????????}????????@Override????????public?int?getCount()?{????????????return?list.size();????????}????????@Override????????public?boolean?isViewFromObject(View?arg0,?Object?arg1)?{????????????return?arg0?==?arg1;????????}????????@Override????????public?void?destroyItem(ViewGroup?container,?int?position,?Object?object)?{????????????container.removeView(list.get(position));????????}????????@Override????????public?Object?instantiateItem(ViewGroup?container,?int?position)?{????????????View?v?=?list.get(position);????????????container.addView(v);????????????return?v;????????}????}}

清單文件

<?xml?version="1.0"?encoding="utf-8"?><manifest?xmlns:android="http://schemas.android.com/apk/res/android"????package="com.example.slidingfinish"????android:versionCode="1"????android:versionName="1.0"?>????<uses-sdk????????android:minSdkVersion="17"????????android:targetSdkVersion="19"?/>????<application????????android:allowBackup="true"????????android:icon="@drawable/ic_launcher"????????android:label="@string/app_name"????????android:theme="@android:style/Theme.Translucent"?>????????<activity????????????android:name=".MainActivity"????????????android:label="@string/app_name"????????????android:theme="@android:style/Theme.Holo.Light"?>????????????<intent-filter>????????????????<action?android:name="android.intent.action.MAIN"?/>????????????????<category?android:name="android.intent.category.LAUNCHER"?/>????????????</intent-filter>????????</activity>????????<activity?android:name=".ListViewActivity"?/>????????<activity?android:name=".NormalActivity"?/>????????<activity?android:name=".ViewPagerActivity"?/>????</application></manifest>

附件列表

?

總結

以上是生活随笔為你收集整理的【右滑返回】滑动冲突 Scroller DecorView的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。