亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android App中實現向右滑動銷毀功能的要點解析

2019-12-12 06:41:50
字體:
來源:轉載
供稿:網友

今天給大家帶來一個向右滑動銷毀Activity的效果,Activtiy隨著手指的移動而移動,該效果在Android應用中還是比較少見的,在IOS中就比較常見了,例如“網易新聞” ,"美食杰" , "淘寶"等應用采用此效果,而Android應用中“知乎”采用的也是這種滑動切換Activity的效果, 不過我發現“淘寶”并沒有隨著手勢的移動而移動,只是捕捉到滑動手勢,然后產生平滑切換界面的動畫效果,這個在Android中還是很好實現的,  網上很多滑動切換Activity的Demo貌似都是這種效果的吧,如果要實現類似“網易新聞”的隨手勢的滑動而滑動,似乎就要復雜一些了,我之前在IOS中看到"網易新聞"的這種效果就很感興趣,然后群里也有朋友問我怎么實現類似“知乎”這個應用的滑動切換的效果,我也特意去下了一個“知乎”,在之前的實現中我遇到了一些瓶頸,沒有實現出來就擱置了在那里,今天無意中看到給Activity設置透明的背景,于是乎我恍然大悟,真是靈感來源于瞬間,不能強求啊,然后自己就將此效果實現了出來,給大家分享一下,希望給有此需求的你一點點幫助。
不知道大家對Scroller這個類以及View的scrollBy() 和scrollTo()的使用熟悉不?我之前介紹了Scroller類的滑動實現原理Android 帶你從源碼的角度解析Scroller的滾動實現原理,在那里面也介紹了scrollBy() 和scrollTo()方法,不明白的同學可以去看看,這對實現此效果有很大的幫助,了解scrollBy() 和scrollTo()的朋友應該知道,如果想對某個View(例如Button)就行滾動,我們直接調用該View(Button)的scrollBy()方法,并不是該View(Button)進行滾動,而是該View里面的內容(Button上面的文字)進行滾動,所以我們假如要讓View整體滾動就需要對其View的父布局調用scrollBy()方法,回到這篇文章來,假如我們想要對一個Activity進行滾動,我們就需求對這個Activity布局文件的頂層布局的父布局進行滾動
例如下面的XML布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"   xmlns:tools="http://schemas.android.com/tools"   android:layout_width="match_parent"   android:layout_height="match_parent"   android:gravity="center"   android:orientation="vertical" >   </LinearLayout> 

如果我們對LinearLayout進行滾動,并不能實現我們想要的效果,而只能對LinearLayout里面的內容或者說是子View進行滾動,所以我們需要獲取利用LinearLayout的getParent()方法獲取父布局,其實Android系統會對我們的布局文件的最外層套一個FrameLayout,所以我們其實就是對FrameLayout進行滾動就行了
了解了實現的原理之后,我們就來編寫代碼吧,首先新建一個android工程,取名SildingFinish
由于我們的需求可能不是在一個界面提供這個滑動切換的效果,所以我們應該將這部分滑動的邏輯抽取出來,我這里就他寫成了一個擴展RelativeLayout的自定義布局SildingFinishLayout,首先我們看其代碼

package com.example.view;  import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.RelativeLayout; import android.widget.ScrollView; import android.widget.Scroller;  /**  * 自定義可以滑動的RelativeLayout, 類似于IOS的滑動刪除頁面效果,當我們要使用  * 此功能的時候,需要將該Activity的頂層布局設置為SildingFinishLayout,  * 然后需要調用setTouchView()方法來設置需要滑動的View  *  * @author xiaanming  *  * @blog http://blog.csdn.net/xiaanming  *  */ public class SildingFinishLayout extends RelativeLayout implements     OnTouchListener {   /**    * SildingFinishLayout布局的父布局    */   private ViewGroup mParentView;   /**    * 處理滑動邏輯的View    */   private View touchView;   /**    * 滑動的最小距離    */   private int mTouchSlop;   /**    * 按下點的X坐標    */   private int downX;   /**    * 按下點的Y坐標    */   private int downY;   /**    * 臨時存儲X坐標    */   private int tempX;   /**    * 滑動類    */   private Scroller mScroller;   /**    * SildingFinishLayout的寬度    */   private int viewWidth;   /**    * 記錄是否正在滑動    */   private boolean isSilding;      private OnSildingFinishListener onSildingFinishListener;   private boolean isFinish;       public SildingFinishLayout(Context context, AttributeSet attrs) {     this(context, attrs, 0);   }    public SildingFinishLayout(Context context, AttributeSet attrs, int defStyle) {     super(context, attrs, defStyle);      mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();     mScroller = new Scroller(context);   }    @Override   protected void onLayout(boolean changed, int l, int t, int r, int b) {     super.onLayout(changed, l, t, r, b);     if (changed) {       // 獲取SildingFinishLayout所在布局的父布局       mParentView = (ViewGroup) this.getParent();       viewWidth = this.getWidth();     }   }    /**    * 設置OnSildingFinishListener, 在onSildingFinish()方法中finish Activity    *    * @param onSildingFinishListener    */   public void setOnSildingFinishListener(       OnSildingFinishListener onSildingFinishListener) {     this.onSildingFinishListener = onSildingFinishListener;   }    /**    * 設置Touch的View    *    * @param touchView    */   public void setTouchView(View touchView) {     this.touchView = touchView;     touchView.setOnTouchListener(this);   }    public View getTouchView() {     return touchView;   }    /**    * 滾動出界面    */   private void scrollRight() {     final int delta = (viewWidth + mParentView.getScrollX());     // 調用startScroll方法來設置一些滾動的參數,我們在computeScroll()方法中調用scrollTo來滾動item     mScroller.startScroll(mParentView.getScrollX(), 0, -delta + 1, 0,         Math.abs(delta));     postInvalidate();   }    /**    * 滾動到起始位置    */   private void scrollOrigin() {     int delta = mParentView.getScrollX();     mScroller.startScroll(mParentView.getScrollX(), 0, -delta, 0,         Math.abs(delta));     postInvalidate();   }    /**    * touch的View是否是AbsListView, 例如ListView, GridView等其子類    *    * @return    */   private boolean isTouchOnAbsListView() {     return touchView instanceof AbsListView ? true : false;   }    /**    * touch的view是否是ScrollView或者其子類    *    * @return    */   private boolean isTouchOnScrollView() {     return touchView instanceof ScrollView ? true : false;   }    @Override   public boolean onTouch(View v, MotionEvent event) {     switch (event.getAction()) {     case MotionEvent.ACTION_DOWN:       downX = tempX = (int) event.getRawX();       downY = (int) event.getRawY();       break;     case MotionEvent.ACTION_MOVE:       int moveX = (int) event.getRawX();       int deltaX = tempX - moveX;       tempX = moveX;       if (Math.abs(moveX - downX) > mTouchSlop           && Math.abs((int) event.getRawY() - downY) < mTouchSlop) {         isSilding = true;          // 若touchView是AbsListView,         // 則當手指滑動,取消item的點擊事件,不然我們滑動也伴隨著item點擊事件的發生         if (isTouchOnAbsListView()) {           MotionEvent cancelEvent = MotionEvent.obtain(event);           cancelEvent               .setAction(MotionEvent.ACTION_CANCEL                   | (event.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));           v.onTouchEvent(cancelEvent);         }        }        if (moveX - downX >= 0 && isSilding) {         mParentView.scrollBy(deltaX, 0);          // 屏蔽在滑動過程中ListView ScrollView等自己的滑動事件         if (isTouchOnScrollView() || isTouchOnAbsListView()) {           return true;         }       }       break;     case MotionEvent.ACTION_UP:       isSilding = false;       if (mParentView.getScrollX() <= -viewWidth / 2) {         isFinish = true;         scrollRight();       } else {         scrollOrigin();         isFinish = false;       }       break;     }      // 假如touch的view是AbsListView或者ScrollView 我們處理完上面自己的邏輯之后     // 再交給AbsListView, ScrollView自己處理其自己的邏輯     if (isTouchOnScrollView() || isTouchOnAbsListView()) {       return v.onTouchEvent(event);     }      // 其他的情況直接返回true     return true;   }    @Override   public void computeScroll() {     // 調用startScroll的時候scroller.computeScrollOffset()返回true,     if (mScroller.computeScrollOffset()) {       mParentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());       postInvalidate();        if (mScroller.isFinished()) {          if (onSildingFinishListener != null && isFinish) {           onSildingFinishListener.onSildingFinish();         }       }     }   }       public interface OnSildingFinishListener {     public void onSildingFinish();   }  } 

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

接下來看onTouch()方法
首先我們在ACTION_DOWN記錄按下點的X,Y坐標
然后在ACTION_MOVE中判斷,如果我們在水平方向滑動的距離大于mTouchSlop并且在豎直方向滑動的距離小于mTouchSlop,表示Activity處于滑動狀態,我們判斷如果touchView是ListView、GridView或者其子類的時候,因為我們手指在ListView、GridView上面,伴隨著item的點擊事件的發生,所以我們對touchView設置ACTION_CANCEL來取消item的點擊事件,然后對該布局的父布局調用scrollBy()進行滾動,并且如果TouchView是AbsListView或者ScrollView直接返回true,來取消AbsListView或者ScrollView本身的ACTION_MOVE事件,最直觀的感受就是我們在滑動Activity的時候,禁止AbsListView或者ScrollView的上下滑動
最后在ACTION_UP中判斷如果手指滑動的距離大于控件長度的二分之一,表示將Activity滑出界面,否則滑動到起始位置,我們利用Scroller類的startScroll()方法設置好開始位置,滑動距離和時間,然后調用postInvalidate()刷新界面,之后就到computeScroll()方法中,我們利用scrollTo()方法對該布局的父布局進行滾動,滾動結束之后,我們判斷界面是否滑出界面,如果是就調用OnSildingFinishListener接口的onSildingFinish()方法,所以只要在onSildingFinish()方法中finish界面就行了
整個滑動布局的代碼就是這個樣子,接下來我們就來使用了,主界面Activity只有三個按鈕,分別跳轉到普通布局的Activity,有ListView的Activity和有ScrollView的Activity中

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"   xmlns:tools="http://schemas.android.com/tools"   android:layout_width="match_parent"   android:layout_height="match_parent"   android:gravity="center"   android:orientation="vertical" >    <Button     android:id="@+id/normal_activity"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:text="普通的Activity" />    <Button     android:id="@+id/absListview_activity"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:text="有AbsListView的Activity" />    <Button     android:id="@+id/scrollview_activity"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:text="有ScrollView的Activity" />  </LinearLayout> 

 
然后就是MainActivity的代碼,根據ID實例化Button,然后為Button設置OnClickListener事件,不同的按鈕跳轉到不同的Activity,然后設置從右向左滑動的動畫,重寫onBackPressed()方法,當我們按下手機物理鍵盤的返回鍵,添加從左向右滑出的動畫

package com.example.slidingfinish;  import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.Button;  import com.example.slidingfinish.R;  public class MainActivity extends Activity implements OnClickListener {    @Override   protected void onCreate(Bundle savedInstanceState) {     requestWindowFeature(Window.FEATURE_NO_TITLE);     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_main);      Button mButtonNormal = (Button) findViewById(R.id.normal_activity);     mButtonNormal.setOnClickListener(this);      Button mButtonAbs = (Button) findViewById(R.id.absListview_activity);     mButtonAbs.setOnClickListener(this);      Button mButtonScroll = (Button) findViewById(R.id.scrollview_activity);     mButtonScroll.setOnClickListener(this);    }    @Override   public void onClick(View v) {     Intent mIntent = null;     switch (v.getId()) {     case R.id.normal_activity:       mIntent = new Intent(MainActivity.this, NormalActivity.class);       break;     case R.id.absListview_activity:       mIntent = new Intent(MainActivity.this, AbsActivity.class);       break;     case R.id.scrollview_activity:       mIntent = new Intent(MainActivity.this, ScrollActivity.class);       break;     }      startActivity(mIntent);     overridePendingTransition(R.anim.base_slide_right_in, R.anim.base_slide_remain);   }      //Press the back button in mobile phone   @Override   public void onBackPressed() {     super.onBackPressed();     overridePendingTransition(0, R.anim.base_slide_right_out);   }  } 

在這里我之貼出含有ListView的Activity的代碼,先看布局,我們自定義滑動布局SildingFinishLayout應該放在XML的最頂層

<?xml version="1.0" encoding="UTF-8"?> <com.example.view.SildingFinishLayout xmlns:android="http://schemas.android.com/apk/res/android"   xmlns:tools="http://schemas.android.com/tools"   android:id="@+id/sildingFinishLayout"   android:layout_width="match_parent"   android:layout_height="match_parent"   android:background="#556677" >    <ListView     android:id="@+id/listView"     android:cacheColorHint="@android:color/transparent"     android:layout_width="match_parent"     android:layout_height="match_parent" >   </ListView>       </com.example.view.SildingFinishLayout> 
package com.example.slidingfinish;  import java.util.ArrayList; import java.util.List;  import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.Window; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.ListView;  import com.example.slidingfinish.R; import com.example.view.SildingFinishLayout; import com.example.view.SildingFinishLayout.OnSildingFinishListener;  public class AbsActivity extends Activity {   private List<String> list = new ArrayList<String>();    @Override   protected void onCreate(Bundle savedInstanceState) {     requestWindowFeature(Window.FEATURE_NO_TITLE);     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_abslistview);      for (int i = 0; i <= 30; i++) {       list.add("測試數據" + i);     }      ListView mListView = (ListView) findViewById(R.id.listView);     ArrayAdapter<String> adapter = new ArrayAdapter<String>(         AbsActivity.this, android.R.layout.simple_list_item_1, list);     mListView.setAdapter(adapter);      SildingFinishLayout mSildingFinishLayout = (SildingFinishLayout) findViewById(R.id.sildingFinishLayout);     mSildingFinishLayout         .setOnSildingFinishListener(new OnSildingFinishListener() {            @Override           public void onSildingFinish() {             AbsActivity.this.finish();           }         });      // touchView要設置到ListView上面     mSildingFinishLayout.setTouchView(mListView);      mListView.setOnItemClickListener(new OnItemClickListener() {        @Override       public void onItemClick(AdapterView<?> parent, View view,           int position, long id) {          startActivity(new Intent(AbsActivity.this, NormalActivity.class));         overridePendingTransition(R.anim.base_slide_right_in,             R.anim.base_slide_remain);       }     });   }    // Press the back button in mobile phone   @Override   public void onBackPressed() {     super.onBackPressed();     overridePendingTransition(0, R.anim.base_slide_right_out);   }  } 

利用ID找到SildingFinishLayout實例,利用setTouchView()方法設置touchView到ListView上面,然后調用setOnSildingFinishListener()設置OnSildingFinishListener,在onSildingFinish()中finish界面就可以啦。
在運行項目之前還有一個很重要的操作,也是之前我被卡到的問題,就是我們需要對Activity設置為透明,即設置主題android:theme="@android:style/Theme.Translucent"

<activity       android:name=".AbsActivity"       android:theme="@android:style/Theme.Translucent" >     </activity>     <activity       android:name=".NormalActivity"       android:theme="@android:style/Theme.Translucent" >     </activity>     <activity       android:name=".ScrollActivity"       android:theme="@android:style/Theme.Translucent" >     </activity> 

 
好了,現在我們可以運行項目看看效果啦

正是我們想要的效果,如果想要加入滑動切換界面的效果只需要三步就行了,首先將Activity布局的最外層修改為SildingFinishLayout,然后在Activity里面調用setTouchView()方法設置touchView,設置OnSildingFinishListener監聽在onSildingFinish()方法中finish界面,最后設置Activity的背景為透明(不是設置Activity布局文件的最頂層布局背景顏色透明,這點要區分一下)是不是很方便呢?好了,今天的講解到這里就結束了~

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91在线视频导航| 国产精品欧美日韩| 97国产suv精品一区二区62| 国外视频精品毛片| 亚洲国内高清视频| 亚洲精选中文字幕| 国产一区二区三区在线视频| 国产精品久久久久秋霞鲁丝| 国产精品视频网站| 亚洲欧美另类中文字幕| 91在线免费看网站| 国产精品精品一区二区三区午夜版| 2019亚洲日韩新视频| 91久久久久久久| 日韩亚洲成人av在线| 国产亚洲在线播放| 97涩涩爰在线观看亚洲| 色狠狠久久aa北条麻妃| 欧美一区深夜视频| 久久视频这里只有精品| 欧美极品少妇xxxxⅹ喷水| 日韩欧美精品免费在线| 色偷偷av亚洲男人的天堂| 亚洲精品二三区| 日韩av电影手机在线观看| 国产91热爆ts人妖在线| 亚洲新声在线观看| 亚洲国产又黄又爽女人高潮的| 中文字幕亚洲天堂| 日韩电视剧免费观看网站| 日本高清视频一区| 午夜精品理论片| 欧美视频在线免费看| 国产在线高清精品| 中文字幕v亚洲ⅴv天堂| 精品国产福利在线| 亚洲国产成人久久综合一区| 日本视频久久久| 欧美精品在线观看91| 久久视频在线直播| 国产精品久久91| 欧美极度另类性三渗透| 欧美一区二区三区……| 亚洲欧洲在线观看| 久久久久久久久久久免费精品| 日韩欧美一区二区在线| 欧美激情一区二区三区高清视频| 韩国19禁主播vip福利视频| 亚洲欧美福利视频| 欧美国产日本高清在线| 亚洲男人7777| 久久精品一区中文字幕| 中文字幕日韩在线视频| 欧美电影在线观看完整版| 久久久久久com| 成人伊人精品色xxxx视频| 最近2019中文免费高清视频观看www99| 97精品久久久| 国产一区二区三区网站| 91高清视频在线免费观看| 国产精品第一视频| 亚洲影视中文字幕| 日韩在线小视频| 国产精品久久久久国产a级| 成人免费观看a| 日韩天堂在线视频| 亚洲自拍偷拍色片视频| 自拍偷拍免费精品| 综合国产在线观看| 欧美在线中文字幕| 中文字幕免费精品一区| 国产精品成熟老女人| 欧美亚洲激情视频| 欧美极品少妇与黑人| 午夜精品久久久久久久99热浪潮| 国产一区二区三区网站| 欧洲s码亚洲m码精品一区| 91精品久久久久久久久久久久久| 成人激情视频网| 亚洲黄色www网站| 亚洲www在线| 久久在线精品视频| 在线观看中文字幕亚洲| 日韩精品视频在线免费观看| 亚洲а∨天堂久久精品喷水| 国产成人精品综合| 久久精品夜夜夜夜夜久久| 成人精品久久一区二区三区| 国产一区二区三区丝袜| 午夜精品三级视频福利| 欧美成aaa人片在线观看蜜臀| 国产视频精品在线| 51视频国产精品一区二区| 亚洲男女性事视频| 国产精品亚洲欧美导航| 国产精品美女午夜av| 欧美激情亚洲激情| 国产精品福利在线| 亚洲精品成人免费| 日韩欧美精品网址| 国产精品美女主播在线观看纯欲| 成人国产精品色哟哟| 视频一区视频二区国产精品| 久久久亚洲影院| 欧美一区视频在线| 日韩视频欧美视频| 国产精品中文在线| 日本免费一区二区三区视频观看| 欧美视频裸体精品| 欧美精品在线网站| 国产欧美最新羞羞视频在线观看| 在线播放精品一区二区三区| 国产日韩av在线| 日韩在线观看精品| 亚洲国产精品一区二区三区| 欧美丰满少妇xxxxx| 欧美精品性视频| 中文字幕精品久久久久| 国产精品偷伦视频免费观看国产| 国内自拍欧美激情| 国产精品自产拍在线观| 亚洲人午夜精品免费| 91av在线影院| 亚洲成色777777女色窝| 欧美成人国产va精品日本一级| 91麻豆国产语对白在线观看| 98精品国产高清在线xxxx天堂| 国产91热爆ts人妖在线| 狠狠操狠狠色综合网| 久久久久亚洲精品国产| 久久久999精品免费| 亚洲网址你懂得| 久久久国产成人精品| 成人久久精品视频| 久久亚洲精品一区二区| 高清欧美性猛交| 国产91亚洲精品| 91久久久久久久久久久久久| 国产精品久久久一区| 日韩成人小视频| 欧美成人激情视频免费观看| 久久视频这里只有精品| 亚洲女成人图区| 亚洲欧美资源在线| 欧美视频在线观看免费| 91香蕉亚洲精品| 国产精品日日做人人爱| 亚洲精品视频网上网址在线观看| 久久久噜噜噜久久| 亚洲午夜国产成人av电影男同| 尤物九九久久国产精品的分类| 国产精品高潮粉嫩av| 欧美精品18videosex性欧美| 日韩一区二区三区国产| 欧美精品九九久久| 成人国产精品一区二区| 亚洲跨种族黑人xxx| 国产不卡视频在线| 国内免费精品永久在线视频| 91亚洲国产成人精品性色| 国产精品免费在线免费| 亚洲欧美一区二区精品久久久| 欧美日韩国产色视频| 国模叶桐国产精品一区|