Android编程实现小说阅读器滑动效果的方法

本文实例讲述了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程序设计有所帮助。

(0)

相关推荐

  • android阅读器长按选择文字功能实现代码

    前言: 有时候我们需要实现长按选择文字功能,比如阅读器一般都有这个功能,有时候某个自定义控件上可能就有这种需求,如何实现呢?正好最近还算闲,想完善一下自己写的那个轻量级的txt文件阅读器(比如这个长按选择文字的功能就想加进去).于是花了两三天时间,实现了这个功能,效果还是不错的. 首先先看看效果图吧: 授人以鱼不如授人以渔,下面具体实现原理的教程. 1.实现原理 原理其实也不难,简单总结就是:绘制文字时把显示的文字的坐标记录下来(记录文字的左上右上左下右下四个点坐标),作用就是为了计算滑动范围.

  • Android实现阅读进度记忆功能

    本文实例为大家分享了Android控件WebView实现保存阅读进度的具体代码,供大家参考,具体内容如下 用户提了一个要求,要求保存他的阅读进度,然后在他下次阅读的时候可以继续阅读,然后动手实现了一下,是这样的. 我用的控件是WebView public class WebViewClientEmb extends WebViewClient { // 在WebView中而不是系统默认浏览器中显示页面 @Override public boolean shouldOverrideUrlLoadi

  • android仿新闻阅读器菜单弹出效果实例(附源码DEMO下载)

    开发中碰到问题之后实现的,觉得可能有的开发者用的到或则希望独立成一个小功能DEMO,所以就放出来这么一个DEMO. 原本觉得是最后完成后发网站客户端的,可是这样体现不出一个功能一个功能的分析实现效果,而且周期时间长,所以就完成一部分,发一部分,敬请谅解. 下面的菜单弹出效果在很多的新闻阅读器上都有,比如今日头条.360新闻等. 其实这个实现起来很简单,看其效果,其实就是一个PopupWindow,之后设定相应postion的按钮点击属性,之后获取按钮的位置,给它设置动画显示消失就可以出现了. 下

  • Android实现阅读APP平移翻页效果

    自己做的一个APP需要用到翻页阅读,网上看过立体翻页效果,不过bug太多了还不兼容.看了一下多看阅读翻页是采用平移翻页的,于是就仿写了一个平移翻页的控件.效果如下: 在翻页时页面右边缘绘制了阴影,效果还不错.要实现这种平移翻页控件并不难,只需要定义一个布局管理页面就可以了.具体实现上有以下难点: 1.循环翻页,页面的重复利用. 2.在翻页时过滤掉多点触碰. 3.采用setAdapter的方式设置页面布局和数据. 下面就来一一解决这几个难点.首先看循环翻页问题,怎么样能采用较少的页面实现这种翻页呢

  • Android编程实现小说阅读器滑动效果的方法

    本文实例讲述了Android编程实现小说阅读器滑动效果的方法.分享给大家供大家参考,具体如下: 看过小说都知道小说阅读器翻页有好多种效果,比如仿真翻页,滑动翻页,等等.由于某种原因,突然想写一个简单点的滑动翻页效果.在这里写出来也没有什么意图,希望大家可以根据这个效果举一反三,写出其他的效果.图就不上了. 下面是代码:大家理解onTouch事件即可 package com.example.testscroll.view; import android.content.Context; impor

  • Android编程之界面跳动提示动画效果实现方法

    本文实例讲述了Android编程之界面跳动提示动画效果实现方法.分享给大家供大家参考,具体如下: 上一个效果图: 先上布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" a

  • Android编程设定activity进入和退出效果的方法

    本文实例讲述了Android编程设定activity进入和退出效果的方法.分享给大家供大家参考,具体如下: 看了android的源代码和资源文件,终于明白如何去修改设置Dialog和Activity的进入和退出效果了.设置Dialog首先通过getWindow()方法获取它的窗口,然后通过getAttributes()方法获得window的WindowManager.LayoutParams lp, lp有个公共属性windowAnimations, 只要把要实现的animation的id赋值给

  • Android编程实现ImageView图片抛物线动画效果的方法

    本文实例讲述了Android编程实现ImageView图片抛物线动画效果的方法.分享给大家供大家参考,具体如下: 想实现抛物线动画,必须知道抛物线的方程,这时候数学其作用了,假如有如图的抛物线: 按照抛物线的方程特别,知道任何的三点可以确定一条抛物线,由已知抛物线的标注 方程为 y = ax² + bx + c:假设A1坐标为(0,0),A2坐标为(300,0),A3坐标为(150,300):联合解方程得知该抛物线的方程为 y = -1/75 x² + 4x:由此方程,我们可以确定抛物线x和y的

  • Android编程中ViewPage判断左右滑动方向的方法

    本文实例讲述了Android编程中ViewPage判断左右滑动方向的方法.分享给大家供大家参考,具体如下: package com.meityitian.app.views; import android.content.Context; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.util.Log; import com.meityitian.app.uti

  • Android编程实现上方通知栏里闪动效果的方法

    本文实例讲述了Android编程实现上方通知栏里闪动效果的方法.分享给大家供大家参考,具体如下: 显示通知代码: private void showNotification(Context ctx, String url) { Notification n = new Notification(); n.flags |= Notification.FLAG_SHOW_LIGHTS; n.flags |= Notification.FLAG_AUTO_CANCEL; n.defaults = No

  • Android编程实现ViewPager多页面滑动切换及动画效果的方法

    本文实例讲述了Android编程实现ViewPager多页面滑动切换及动画效果的方法.分享给大家供大家参考,具体如下: 一.首先,我们来看一下效果图,这是新浪微博的Tab滑动效果.我们可以手势滑动,也可以点击上面的头标进行切换.与此同方式, 白色横条会移动到相应的页卡头标下.这是一个动画效果,白条是缓慢滑动过去的.好了,接下来我们就来实现它. 二.在开始前,我们先要认识一个控件,ViewPager.它是google SDk中自带的一个附加包的一个类,可以用来实现屏幕间的切换. 这个附加包是and

  • Android编程实现Gallery中每次滑动只显示一页的方法

    本文实例讲述了Android编程实现Gallery中每次滑动只显示一页的方法.分享给大家供大家参考,具体如下: import android.content.Context; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.MotionEvent; import android.widget.Gallery; public class DetialGallery extends

  • 用python给自己做一款小说阅读器过程详解

    前言 前一段时间书荒的时候,在喜马拉雅APP发现一个主播播讲的小说-大王饶命.听起来感觉很好笑,挺有意思的,但是只有前200张是免费的,后面就要收费.一章两毛钱,本来是想要买一下,发现说的进度比较慢而且整本书要1300多张,算了一下,需要200大洋才行,而且等他说完,还不知道要到什么时候去. 所以就找文字版的来读,文字版又有它的缺点,你必须手眼联动才行.如果要忙别的事情,但是又抑制不住想看的冲动,就很纠结了.在网上找了一圈,没有其他的音频.而且以前用的那些有阅读功能的软件,比如微信阅读.追书神器

  • android开发通过Scroller实现过渡滑动效果操作示例

    本文实例讲述了android开发通过Scroller实现过渡滑动效果.分享给大家供大家参考,具体如下: 主要介绍一下Scroller这个类,它可以实现过渡滑动的效果,使滑动看起来不是那么生硬,当然它用大量的重绘来实现,invalidate();通过源码看: 看构造方法 /** * Create a Scroller with the default duration and interpolator. */ public Scroller(Context context) { this(cont

随机推荐