业界动态
android 阅读器自动滚动,Android编程实现小说阅读器滑动效果的方法
2024-12-26 22:33

本文实例讲述了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;

private View mScrollerView = null;

private View currentTopView = null;

private View currentShowView = null;

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;

}

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);

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,即复位

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;

}

}

public interface TouchListener {

final int MOVE_TO_LEFT = 0;

final int MOVE_TO_RIGHT = 1;

public View createView(final int direction);

public boolean currentIsFirstPage();

public boolean currentIsLastPage();

public boolean whetherHasPreviousPage();

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布局文件

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="horizontal" >

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" />

android:layout_width="5dp"

android:layout_height="match_parent"

android:background="#FFFF00"

android:gravity="center"

android:textSize="25sp"

android:visibility="visible" />

activity布局文件

xmlns:tools="http://schemas.android.com/tools"

android:id="@+id/container"

android:layout_width="match_parent"

android:layout_height="match_parent" >

备注:上面为什么加一个速率计算器呢,其实只是为了识别这个动作是不是快速滑动的动作,就算滑动的距离不到屏幕的1/3,但是只要速率满足都可以判定改滑动是一个翻页的动作。

注意哦:这只是其中一个滑动的效果而已啊,不包括小说分章节的逻辑哦。虽然有些粗糙,但是还是有可以值得学习的地方,大家如果还有什么好的解决方案,可以一起讨论。

附上demo下载地址 点击下载demo。

    以上就是本篇文章【android 阅读器自动滚动,Android编程实现小说阅读器滑动效果的方法】的全部内容了,欢迎阅览 ! 文章地址:https://sicmodule.kub2b.com/news/10524.html
     栏目首页      相关文章      动态      同类文章      热门文章      网站地图      返回首页 企库往资讯移动站 https://sicmodule.kub2b.com/mobile/ , 查看更多   
最新文章
发改委:推进户用光伏发展,助力农民拓宽增收新路径
中国产品流通经纪人协会供销合作行业标准《农产品食品供应商信用评价规范》参编单位征集函中国农产品流通经纪人协会供销合作行业
泉州百度爱采购运营介绍
百度爱采购入驻条件有哪些:商家需持有工商行政管理局颁发的营业执照,并且执照在6个月有效期内;厂家商品真实在营且符合国家相
抖音feed是什么 feed广告投放流程
feed是什么?feed流(又称信息流)它是穿插在App内容中的广告,具有原生沉浸式体验,支持多种展现形式。feed可以进行线索收集,
抖音投流怎么投?找到最合适的优化路线,实现精准引流与高效转化!
在如今竞争激烈的市场中,抖音广告已经成为商家吸引流量、增加曝光和转化的重要工具。很多企业都在问:“抖音投流怎么投,才能真
提升脸书播放/浏览量:Facebook Workplace的策略
以下介绍:提升脸书播放/浏览量:Facebook Workplace的策略关于提升脸书播放/浏览量:Facebook Workplace的策略所提到的问题请大
想换07年左右的老车,值得吗?
百车全说别人研究车,而我研究你!问:想买一辆2007年左右,绿色(丨), 3.0。主要是喜欢这种雪茄车身,想留着自己偶尔开一下,家
年度盘点丨西安:2024年度十大交通精细化治理案例
​​2024年,西安公安交警深入践行以人民为中心的发展思想,聚焦群众反映强烈的交通问题,坚持缓堵保畅、全域治理,坚持小切口入
怎样才能很好的提高百度SEO的排名呢
怎样使自己的网站在百度等搜索引擎排名靠前  提高用户体验确保网站加载速度快,移动设备友好,并提供良好的用户互动体验。利用
《人工智能:未来世界的“智慧引擎”》
在当今这个科技飞速发展的时代,人工智能(Artificial Intelligence,简称AI)正以前所未有的速度重塑
未来直播技术的创新与发展方向
随着信息技术的快速发展和移动互联网的广泛普及,直播已经成为当今互联网领域的重要应用之一。从最初的娱乐直播到现在的教育直播