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

首頁 > 系統 > Android > 正文

Android編程實現小說閱讀器滑動效果的方法

2020-04-11 11:21:11
字體:
來源:轉載
供稿:網友

本文實例講述了Android編程實現小說閱讀器滑動效果的方法。分享給大家供大家參考,具體如下:

看過小說都知道小說閱讀器翻頁有好多種效果,比如仿真翻頁,滑動翻頁,等等。由于某種原因,突然想寫一個簡單點的滑動翻頁效果。在這里寫出來也沒有什么意圖,希望大家可以根據這個效果舉一反三,寫出其他的效果。圖就不上了。

下面是代碼:大家理解onTouch事件即可

package com.example.testscroll.view; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.Scroller; public class FlipperLayout extends ViewGroup {  private Scroller mScroller;  private VelocityTracker mVelocityTracker;  private int mVelocityValue = 0;  /** 商定這個滑動是否有效的距離 */  private int limitDistance = 0;  private int screenWidth = 0;  /** 手指移動的方向 */  private static final int MOVE_TO_LEFT = 0;  private static final int MOVE_TO_RIGHT = 1;  private static final int MOVE_NO_RESULT = 2;  /** 最后觸摸的結果方向 */  private int mTouchResult = MOVE_NO_RESULT;  /** 一開始的方向 */  private int mDirection = MOVE_NO_RESULT;  /** 觸摸的模式 */  private static final int MODE_NONE = 0;  private static final int MODE_MOVE = 1;  private int mMode = MODE_NONE;  /** 滑動的view */  private View mScrollerView = null;  /** 最上層的view(處于邊緣的,看不到的) */  private View currentTopView = null;  /** 顯示的view,顯示在屏幕 */  private View currentShowView = null;  /** 最底層的view(看不到的) */  private View currentBottomView = null;  public FlipperLayout(Context context) {   super(context);   init(context);  }  public FlipperLayout(Context context, AttributeSet attrs, int defStyle) {   super(context, attrs, defStyle);   init(context);  }  public FlipperLayout(Context context, AttributeSet attrs) {   super(context, attrs);   init(context);  }  private void init(Context context) {   mScroller = new Scroller(context);   screenWidth = context.getResources().getDisplayMetrics().widthPixels;   limitDistance = screenWidth / 3;  }  /***   *   * @param listener   * @param currentBottomView   *  最底層的view,初始狀態看不到   * @param currentShowView   *  正在顯示的View   * @param currentTopView   *  最上層的View,初始化時滑出屏幕   */  public void initFlipperViews(TouchListener listener, View currentBottomView, View currentShowView, View currentTopView) {   this.currentBottomView = currentBottomView;   this.currentShowView = currentShowView;   this.currentTopView = currentTopView;   setTouchResultListener(listener);   addView(currentBottomView);   addView(currentShowView);   addView(currentTopView);   /** 默認將最上層的view滑動的邊緣(用于查看上一頁) */   currentTopView.scrollTo(-screenWidth, 0);  }  @Override  protected void onLayout(boolean changed, int l, int t, int r, int b) {   for (int i = 0; i < getChildCount(); i++) {    View child = getChildAt(i);    int height = child.getMeasuredHeight();    int width = child.getMeasuredWidth();    child.layout(0, 0, width, height);   }  }  @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {   super.onMeasure(widthMeasureSpec, heightMeasureSpec);   int width = MeasureSpec.getSize(widthMeasureSpec);   int height = MeasureSpec.getSize(heightMeasureSpec);   setMeasuredDimension(width, height);   for (int i = 0; i < getChildCount(); i++) {    getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);   }  }  private int startX = 0;  @Override  public boolean dispatchTouchEvent(MotionEvent ev) {   switch (ev.getAction()) {   case MotionEvent.ACTION_DOWN:    if (!mScroller.isFinished()) {     break;    }    startX = (int) ev.getX();    break;   }   return super.dispatchTouchEvent(ev);  }  @SuppressWarnings("deprecation")  @Override  public boolean onTouchEvent(MotionEvent event) {   obtainVelocityTracker(event);   switch (event.getAction()) {   case MotionEvent.ACTION_MOVE:    if (!mScroller.isFinished()) {     return super.onTouchEvent(event);    }    if (startX == 0) {     startX = (int) event.getX();    }    final int distance = startX - (int) event.getX();    if (mDirection == MOVE_NO_RESULT) {     if (mListener.whetherHasNextPage() && distance > 0) {      mDirection = MOVE_TO_LEFT;     } else if (mListener.whetherHasPreviousPage() && distance < 0) {     mDirection = MOVE_TO_RIGHT;     }    }    if (mMode == MODE_NONE      && ((mDirection == MOVE_TO_LEFT && mListener.whetherHasNextPage()) || (mDirection == MOVE_TO_RIGHT && mListener        .whetherHasPreviousPage()))) {     mMode = MODE_MOVE;    }    if (mMode == MODE_MOVE) {     if ((mDirection == MOVE_TO_LEFT && distance <= 0) || (mDirection == MOVE_TO_RIGHT && distance >= 0)) {      mMode = MODE_NONE;     }    }    if (mDirection != MOVE_NO_RESULT) {     if (mDirection == MOVE_TO_LEFT) {      if (mScrollerView != currentShowView) {       mScrollerView = currentShowView;      }     } else {      if (mScrollerView != currentTopView) {       mScrollerView = currentTopView;      }     }     if (mMode == MODE_MOVE) {      mVelocityTracker.computeCurrentVelocity(1000, ViewConfiguration.getMaximumFlingVelocity());      if (mDirection == MOVE_TO_LEFT) {       mScrollerView.scrollTo(distance, 0);      } else {       mScrollerView.scrollTo(screenWidth + distance, 0);      }     } else {      final int scrollX = mScrollerView.getScrollX();      if (mDirection == MOVE_TO_LEFT && scrollX != 0 && mListener.whetherHasNextPage()) {       mScrollerView.scrollTo(0, 0);      } else if (mDirection == MOVE_TO_RIGHT && mListener.whetherHasPreviousPage() && screenWidth != Math.abs(scrollX)) {       mScrollerView.scrollTo(-screenWidth, 0);      }     }    }    break;   case MotionEvent.ACTION_UP:    if (mScrollerView == null) {     return super.onTouchEvent(event);    }    final int scrollX = mScrollerView.getScrollX();    mVelocityValue = (int) mVelocityTracker.getXVelocity();    // scroll左正,右負(),(startX + dx)的值如果為0,即復位    /*     * android.widget.Scroller.startScroll( int startX, int startY, int     * dx, int dy, int duration )     */    int time = 500;    if (mMode == MODE_MOVE && mDirection == MOVE_TO_LEFT) {     if (scrollX > limitDistance || mVelocityValue < -time) {      // 手指向左移動,可以翻屏幕      mTouchResult = MOVE_TO_LEFT;      if (mVelocityValue < -time) {       time = 200;      }      mScroller.startScroll(scrollX, 0, screenWidth - scrollX, 0, time);     } else {      mTouchResult = MOVE_NO_RESULT;      mScroller.startScroll(scrollX, 0, -scrollX, 0, time);     }    } else if (mMode == MODE_MOVE && mDirection == MOVE_TO_RIGHT) {     if ((screenWidth - scrollX) > limitDistance || mVelocityValue > time) {      // 手指向右移動,可以翻屏幕      mTouchResult = MOVE_TO_RIGHT;      if (mVelocityValue > time) {       time = 250;      }      mScroller.startScroll(scrollX, 0, -scrollX, 0, time);     } else {      mTouchResult = MOVE_NO_RESULT;      mScroller.startScroll(scrollX, 0, screenWidth - scrollX, 0, time);     }    }    resetVariables();    postInvalidate();    break;   }   return true;  }  private void resetVariables() {   mDirection = MOVE_NO_RESULT;   mMode = MODE_NONE;   startX = 0;   releaseVelocityTracker();  }  private TouchListener mListener;  private void setTouchResultListener(TouchListener listener) {   this.mListener = listener;  }  @Override  public void computeScroll() {   super.computeScroll();   if (mScroller.computeScrollOffset()) {    mScrollerView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());   postInvalidate();   } else if (mScroller.isFinished() && mListener != null && mTouchResult != MOVE_NO_RESULT) {    if (mTouchResult == MOVE_TO_LEFT) {     if (currentTopView != null) {      removeView(currentTopView);     }     currentTopView = mScrollerView;     currentShowView = currentBottomView;     if (mListener.currentIsLastPage()) {      final View newView = mListener.createView(mTouchResult);      currentBottomView = newView;      addView(newView, 0);     } else {      currentBottomView = new View(getContext());      currentBottomView.setVisibility(View.GONE);      addView(currentBottomView, 0);     }    } else {     if (currentBottomView != null) {      removeView(currentBottomView);     }     currentBottomView = currentShowView;     currentShowView = mScrollerView;     if (mListener.currentIsFirstPage()) {      final View newView = mListener.createView(mTouchResult);      currentTopView = newView;      currentTopView.scrollTo(-screenWidth, 0);      addView(currentTopView);     } else {      currentTopView = new View(getContext());      currentTopView.scrollTo(-screenWidth, 0);      currentTopView.setVisibility(View.GONE);      addView(currentTopView);     }    }    mTouchResult = MOVE_NO_RESULT;   }  }  private void obtainVelocityTracker(MotionEvent event) {   if (mVelocityTracker == null) {    mVelocityTracker = VelocityTracker.obtain();   }   mVelocityTracker.addMovement(event);  }  private void releaseVelocityTracker() {   if (mVelocityTracker != null) {    mVelocityTracker.recycle();    mVelocityTracker = null;   }  }  /***   * 用來實時回調觸摸事件回調   *   * @author freeson   */  public interface TouchListener {   /** 手指向左滑動,即查看下一章節 */   final int MOVE_TO_LEFT = 0;   /** 手指向右滑動,即查看上一章節 */   final int MOVE_TO_RIGHT = 1;   /**    * 創建一個承載Text的View    *    * @param direction    *   {@link MOVE_TO_LEFT,MOVE_TO_RIGHT}    * @return    */   public View createView(final int direction);   /***    * 當前頁是否是第一頁    *    * @return    */   public boolean currentIsFirstPage();   /***    * 當前頁是否是最后一頁    *    * @return    */   public boolean currentIsLastPage();   /**    * 當前頁是否有上一頁(用來判斷可滑動性)    *    * @return    */   public boolean whetherHasPreviousPage();   /***    * 當前頁是否有下一頁(用來判斷可滑動性)    *    * @return    */   public boolean whetherHasNextPage();  } }

Activity測試文件:

package com.example.testscroll; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import android.app.Activity; import android.content.res.AssetManager; import android.os.Bundle; import android.os.Handler; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; import com.example.testscroll.view.FlipperLayout; import com.example.testscroll.view.FlipperLayout.TouchListener; import com.example.testscrollactivity.R; public class MainActivity extends Activity implements OnClickListener, TouchListener {  private String text = "";  private int textLenght = 0;  private static final int COUNT = 400;  private int currentTopEndIndex = 0;  private int currentShowEndIndex = 0;  private int currentBottomEndIndex = 0;  private Handler handler = new Handler() {   public void handleMessage(android.os.Message msg) {    FlipperLayout rootLayout = (FlipperLayout) findViewById(R.id.container);    View recoverView = LayoutInflater.from(MainActivity.this).inflate(R.layout.view_new, null);    View view1 = LayoutInflater.from(MainActivity.this).inflate(R.layout.view_new, null);    View view2 = LayoutInflater.from(MainActivity.this).inflate(R.layout.view_new, null);    rootLayout.initFlipperViews(MainActivity.this, view2, view1, recoverView);    textLenght = text.length();    System.out.println("----textLenght----->" + textLenght);    TextView textView = (TextView) view1.findViewById(R.id.textview);    if (textLenght > COUNT) {     textView.setText(text.subSequence(0, COUNT));     textView = (TextView) view2.findViewById(R.id.textview);     if (textLenght > (COUNT << 1)) {      textView.setText(text.subSequence(COUNT, COUNT * 2));      currentShowEndIndex = COUNT;      currentBottomEndIndex = COUNT << 1;     } else {      textView.setText(text.subSequence(COUNT, textLenght));      currentShowEndIndex = textLenght;      currentBottomEndIndex = textLenght;     }    } else {     textView.setText(text.subSequence(0, textLenght));     currentShowEndIndex = textLenght;     currentBottomEndIndex = textLenght;    }   };  };  @Override  protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);   setContentView(R.layout.activity_main);   new ReadingThread().start();  }  @Override  public void onClick(View v) {  }  @Override  public View createView(final int direction) {   String txt = "";   if (direction == TouchListener.MOVE_TO_LEFT) {    currentTopEndIndex = currentShowEndIndex;    final int nextIndex = currentBottomEndIndex + COUNT;    currentShowEndIndex = currentBottomEndIndex;    if (textLenght > nextIndex) {     txt = text.substring(currentBottomEndIndex, nextIndex);     currentBottomEndIndex = nextIndex;    } else {     txt = text.substring(currentBottomEndIndex, textLenght);     currentBottomEndIndex = textLenght;    }   } else {    currentBottomEndIndex = currentShowEndIndex;    currentShowEndIndex = currentTopEndIndex;    currentTopEndIndex = currentTopEndIndex - COUNT;    txt = text.substring(currentTopEndIndex - COUNT, currentTopEndIndex);   }   View view = LayoutInflater.from(this).inflate(R.layout.view_new, null);   TextView textView = (TextView) view.findViewById(R.id.textview);   textView.setText(txt);   System.out.println("-top->" + currentTopEndIndex + "-show->" + currentShowEndIndex + "--bottom-->" + currentBottomEndIndex);   return view;  }  @Override  public boolean whetherHasPreviousPage() {   return currentShowEndIndex > COUNT;  }  @Override  public boolean whetherHasNextPage() {   return currentShowEndIndex < textLenght;  }  @Override  public boolean currentIsFirstPage() {   boolean should = currentTopEndIndex > COUNT;   if (!should) {    currentBottomEndIndex = currentShowEndIndex;    currentShowEndIndex = currentTopEndIndex;    currentTopEndIndex = currentTopEndIndex - COUNT;   }   return should;  }  @Override  public boolean currentIsLastPage() {   boolean should = currentBottomEndIndex < textLenght;   if (!should) {    currentTopEndIndex = currentShowEndIndex;    final int nextIndex = currentBottomEndIndex + COUNT;    currentShowEndIndex = currentBottomEndIndex;    if (textLenght > nextIndex) {     currentBottomEndIndex = nextIndex;    } else {     currentBottomEndIndex = textLenght;    }   }   return should;  }  private class ReadingThread extends Thread {   public void run() {    AssetManager am = getAssets();    InputStream response;    try {     response = am.open("text.txt");     if (response != null) {      ByteArrayOutputStream baos = new ByteArrayOutputStream();      int i = -1;      while ((i = response.read()) != -1) {       baos.write(i);      }      text = new String(baos.toByteArray(), "UTF-8");      baos.close();      response.close();      handler.sendEmptyMessage(0);     }    } catch (IOException e) {     e.printStackTrace();    }   }  } }

xml布局文件:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="horizontal" >  <TextView   android:id="@+id/textview"   android:layout_width="0dp"   android:layout_height="match_parent"   android:layout_weight="1.0"   android:background="#666666"   android:gravity="center"   android:text="新建的View"   android:textColor="@android:color/white"   android:textSize="16sp"   android:visibility="visible" />  <View   android:layout_width="5dp"   android:layout_height="match_parent"   android:background="#FFFF00"   android:gravity="center"   android:textSize="25sp"   android:visibility="visible" /></LinearLayout>

activity布局文件:

<com.example.testscroll.view.FlipperLayout xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:tools="http://schemas.android.com/tools"  android:id="@+id/container"  android:layout_width="match_parent"  android:layout_height="match_parent" > </com.example.testscroll.view.FlipperLayout>

備注:上面為什么加一個速率計算器呢,其實只是為了識別這個動作是不是快速滑動的動作,就算滑動的距離不到屏幕的1/3,但是只要速率滿足都可以判定改滑動是一個翻頁的動作。

注意哦:這只是其中一個滑動的效果而已啊,不包括小說分章節的邏輯哦。雖然有些粗糙,但是還是有可以值得學習的地方,大家如果還有什么好的解決方案,可以一起討論。

附上demo下載地址 點擊下載demo。

希望本文所述對大家Android程序設計有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美风情在线观看| 欧美怡红院视频一区二区三区| 九九久久综合网站| 91久久久国产精品| 国产日韩欧美电影在线观看| 久久精品国产综合| 亚洲精品乱码久久久久久金桔影视| 日本一本a高清免费不卡| 欧美大片大片在线播放| 亚洲最大的成人网| 日本精品久久久久影院| 911国产网站尤物在线观看| 97成人精品区在线播放| 久久国产精品久久精品| 欧美俄罗斯性视频| 久久久久中文字幕2018| 精品综合久久久久久97| 成人欧美一区二区三区黑人孕妇| 欧美中文字幕在线播放| 欧美福利视频网站| 2020欧美日韩在线视频| 久久久精品2019中文字幕神马| 91久久久久久久久久久| 日韩精品欧美激情| 日韩高清电影好看的电视剧电影| 欧美亚洲国产视频| 26uuu国产精品视频| 欧美一级视频在线观看| 亚洲最大的免费| 91国产美女视频| 国产精品久久久久久久av大片| 久久99国产综合精品女同| 国产精品女人久久久久久| 国产成人avxxxxx在线看| 成人伊人精品色xxxx视频| 欧美不卡视频一区发布| 亚洲人午夜色婷婷| 日韩av中文字幕在线免费观看| 欧美成人精品在线视频| 92看片淫黄大片欧美看国产片| 亚洲va久久久噜噜噜| 欧美性高潮床叫视频| 欧美老女人xx| 成人在线一区二区| 日韩中文字幕在线免费观看| 国产精品视频久久久久| 97免费视频在线播放| 欧美激情中文网| 在线播放日韩精品| 亚洲图片制服诱惑| 亚洲精品在线不卡| 国产精品视频久久久久| 久久亚洲国产精品成人av秋霞| 欧美日韩国产中字| 欧美成人精品不卡视频在线观看| 久久免费视频在线观看| 永久免费看mv网站入口亚洲| 精品高清一区二区三区| 日韩av电影手机在线观看| 日韩一区二区av| 久久99精品久久久久久噜噜| 国产精品色午夜在线观看| 久久99精品视频一区97| 欧美在线视频网| 日韩欧美中文字幕在线播放| 伊人亚洲福利一区二区三区| 久久亚洲精品成人| 一区二区三区动漫| 日韩大胆人体377p| 亚洲999一在线观看www| 91色中文字幕| 欧美黄色片在线观看| 一区二区三欧美| 欧美体内谢she精2性欧美| 蜜臀久久99精品久久久久久宅男| 欧美性在线观看| 久久人人看视频| 国产91|九色| 国产成人精品视频在线观看| 51ⅴ精品国产91久久久久久| 欧美黄色片视频| 亚洲成人激情在线| 日韩精品极品在线观看播放免费视频| 秋霞av国产精品一区| 欧美精品午夜视频| 亚洲精品美女久久久久| 久久国产天堂福利天堂| 日韩欧美在线第一页| 精品视频久久久| 欧美在线视频在线播放完整版免费观看| 欧美综合在线观看| 日韩av电影在线免费播放| 96精品久久久久中文字幕| 日韩av一区在线| 欧美一区二区三区艳史| www.精品av.com| 国产精品一二三视频| 欧美成人黄色小视频| 亚洲色在线视频| 91av免费观看91av精品在线| 亚洲欧美日韩爽爽影院| 国产乱人伦真实精品视频| 中日韩美女免费视频网址在线观看| 国产精品91一区| 国产一区二区黑人欧美xxxx| 91国内精品久久| 91国产精品视频在线| 精品在线观看国产| 亚洲天堂男人天堂| 久久黄色av网站| 69久久夜色精品国产69| 日韩一区在线视频| 亚洲直播在线一区| 日韩久久免费电影| 久久久精品电影| 欧美成人午夜激情| 夜夜躁日日躁狠狠久久88av| 亚洲精品国产精品自产a区红杏吧| 国产精品揄拍一区二区| 欧美日韩激情视频8区| 亚洲夜晚福利在线观看| 国产主播精品在线| 精品精品国产国产自在线| 成人羞羞国产免费| 亚洲欧美国产另类| 中文国产成人精品久久一| 欧美老少做受xxxx高潮| 精品国产成人在线| 欧美一级高清免费| 欧美日韩视频免费播放| 国产精品尤物福利片在线观看| 欧美洲成人男女午夜视频| 亚洲码在线观看| 欧美裸身视频免费观看| 久久综合伊人77777蜜臀| 精品国产一区二区三区久久| 日本成人精品在线| 九九热这里只有在线精品视| 奇米成人av国产一区二区三区| 亚洲a区在线视频| 欧美性猛交xxxx乱大交蜜桃| 国产精品吹潮在线观看| 午夜精品久久久久久久99热浪潮| 色七七影院综合| 色噜噜狠狠狠综合曰曰曰| 欧美裸体视频网站| 97视频在线观看网址| 国产免费一区二区三区香蕉精| 成人黄色免费片| 日日狠狠久久偷偷四色综合免费| 国产精品亚洲视频在线观看| 久久天堂av综合合色| 青草热久免费精品视频| 国产成人精品在线视频| 高清欧美性猛交xxxx黑人猛交| 国产第一区电影| 国产精品黄色影片导航在线观看| 精品久久香蕉国产线看观看gif| 欧美激情xxxxx| 91亚洲va在线va天堂va国| 亚洲a∨日韩av高清在线观看| 久久久久久久久久久91| 成人黄色av免费在线观看| 国产精品久久久久久久一区探花|