gpt4 book ai didi

android - 如何过度滚动自定义 View (surfaceview)

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:01:39 25 4
gpt4 key购买 nike

我有一个由工作线程管理的自定义 SurfaceView。我使用的代码与以下博客文章中的代码非常相似来管理 SurfaceView:

http://android-coding.blogspot.com/2011/05/drawing-on-surfaceview.html

我的自定义 SurfaceView 在监听触摸事件、将它们发送到手势检测器并实现 onScroll 的意义上是可滚动的。我跟踪一些成员变量(x 轴和 y 轴)中的滚动距离,并在绘制到 Canvas 时将任何坐标平移适当的量。我还固定滚动距离,并且可以在固定时轻松计算和存储任何过度滚动量。

一切正常。

问题是我想在我的自定义 SurfaceView 上显示标准的 Android 过度滚动效果。我尝试手动调用 overScrollBy 但它没有用,我最好的猜测是因为我正在从工作线程绘制 View ,这意味着永远不会调用 View 的 onDraw。

我发现了以下关于自定义滚动效果的 stackoverflow 帖子:

How can I change the OverScroll color in Android 2.3.1?

该帖子不适用于 SurfaceViews,但我可能会调整代码。也就是说,有没有更好的方法?我想显示与其他地方显示的完全相同的过度滚动效果。制作过度滚动可绘制对象的副本并尝试复制过度滚动逻辑似乎……很丑陋。

最佳答案

好吧,我设法通过使用 OverScroller 在简单 View 中组合了一个简单的过度滚动示例:

package net.project.experimental;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.OverScroller;

public class WorksheetView extends View
{
protected static final int OVERSCROLL_DISTANCE = 10;
protected static final int INVALID_POINTER_ID = -1;

private int fWorksheetWidth = 2000;
private int fWorksheetHeight = 2000;

private OverScroller fScroller;
private VelocityTracker fVelocityTracker = null;
private int fMinimumVelocity;

// The ‘active pointer’ is the one currently moving our object.
private int fTranslatePointerId = INVALID_POINTER_ID;
private PointF fTranslateLastTouch = new PointF( );

private boolean fInteracting = false;

public WorksheetView(Context context, AttributeSet attrs)
{
super( context, attrs );
this.initView( context, attrs );
}

public WorksheetView(Context context, AttributeSet attrs, int defStyle)
{
super( context, attrs, defStyle );
this.initView( context, attrs );
}

protected void initView(Context context, AttributeSet attrs)
{
fScroller = new OverScroller( this.getContext( ) );

this.setOverScrollMode( OVER_SCROLL_ALWAYS );

final ViewConfiguration configuration = ViewConfiguration.get( getContext( ) );
//fTouchSlop = configuration.getScaledTouchSlop( );
fMinimumVelocity = configuration.getScaledMinimumFlingVelocity( );
}

@Override
public boolean onTouchEvent(MotionEvent event)
{
if ( fVelocityTracker == null )
{
fVelocityTracker = VelocityTracker.obtain( );
}
fVelocityTracker.addMovement( event );

final int action = event.getAction( );
switch ( action & MotionEvent.ACTION_MASK )
{
case MotionEvent.ACTION_DOWN:
{
if ( !fScroller.isFinished( ) )
fScroller.abortAnimation( );

final float x = event.getX( );
final float y = event.getY( );

fTranslateLastTouch.set( x, y );
fTranslatePointerId = event.getPointerId( 0 );
this.startInteracting( );
break;
}

case MotionEvent.ACTION_MOVE:
{
final int pointerIndexTranslate = event.findPointerIndex( fTranslatePointerId );
if ( pointerIndexTranslate >= 0 )
{
float translateX = event.getX( pointerIndexTranslate );
float translateY = event.getY( pointerIndexTranslate );

this.overScrollBy(
(int) (fTranslateLastTouch.x - translateX),
(int) (fTranslateLastTouch.y - translateY),
this.getScrollX( ),
this.getScrollY( ),
fWorksheetWidth - this.getWidth( ),
fWorksheetHeight - this.getHeight( ),
OVERSCROLL_DISTANCE,
OVERSCROLL_DISTANCE,
true );

fTranslateLastTouch.set( translateX, translateY );

this.invalidate( );
}

break;
}

case MotionEvent.ACTION_UP:
{
final VelocityTracker velocityTracker = fVelocityTracker;
velocityTracker.computeCurrentVelocity( 1000 );
//velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int initialXVelocity = (int) velocityTracker.getXVelocity( );
int initialYVelocity = (int) velocityTracker.getYVelocity( );

if ( (Math.abs( initialXVelocity ) + Math.abs( initialYVelocity ) > fMinimumVelocity) )
{
this.fling( -initialXVelocity, -initialYVelocity );
}
else
{
if ( fScroller.springBack( this.getScrollX( ), this.getScrollY( ), 0, fWorksheetWidth - this.getWidth( ), 0, fWorksheetHeight - this.getHeight( ) ) )
this.invalidate( );

this.stopInteracting( );
}

if ( fVelocityTracker != null )
{
fVelocityTracker.recycle( );
fVelocityTracker = null;
}


fTranslatePointerId = INVALID_POINTER_ID;
break;
}

case MotionEvent.ACTION_POINTER_DOWN:
{
break;
}

case MotionEvent.ACTION_POINTER_UP:
{
final int pointerIndex = (event.getAction( ) & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = event.getPointerId( pointerIndex );
if ( pointerId == fTranslatePointerId )
{
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
fTranslateLastTouch.set( event.getX( newPointerIndex ), event.getY( newPointerIndex ) );
fTranslatePointerId = event.getPointerId( newPointerIndex );
}

break;
}

case MotionEvent.ACTION_CANCEL:
{
if ( fScroller.springBack( this.getScrollX( ), this.getScrollY( ), 0, fWorksheetWidth - this.getWidth( ), 0, fWorksheetHeight - this.getHeight( ) ) )
this.invalidate( );

fTranslatePointerId = INVALID_POINTER_ID;
break;
}
}

return true;
}

private void fling(int velocityX, int velocityY)
{
int x = this.getScrollX( );
int y = this.getScrollY( );

this.startInteracting( );
//fScroller.setFriction( ViewConfiguration.getScrollFriction( ) );
fScroller.fling( x, y, velocityX, velocityY, 0, fWorksheetWidth - this.getWidth( ), 0, fWorksheetHeight - this.getHeight( ) );

this.invalidate( );
}

private void startInteracting()
{
fInteracting = true;
}

private void stopInteracting()
{
fInteracting = false;
}

@Override
public void computeScroll()
{
if ( fScroller != null && fScroller.computeScrollOffset( ) )
{
int oldX = this.getScrollX( );
int oldY = this.getScrollY( );
int x = fScroller.getCurrX( );
int y = fScroller.getCurrY( );

if ( oldX != x || oldY != y )
{
this.overScrollBy(
x - oldX,
y - oldY,
oldX,
oldY,
fWorksheetWidth - this.getWidth( ),
fWorksheetHeight - this.getHeight( ),
OVERSCROLL_DISTANCE,
OVERSCROLL_DISTANCE,
false );
}

if ( fScroller.isFinished( ) )
this.stopInteracting( );

this.postInvalidate( );
}
}

@Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)
{
// Treat animating scrolls differently; see #computeScroll() for why.
if ( !fScroller.isFinished( ) )
{
super.scrollTo( scrollX, scrollY );

if ( clampedX || clampedY )
{
fScroller.springBack( this.getScrollX( ), this.getScrollY( ), 0, fWorksheetWidth - this.getWidth( ), 0, fWorksheetHeight - this.getHeight( ) );
}
}
else
{
super.scrollTo( scrollX, scrollY );
}
awakenScrollBars( );
}

@Override
protected int computeHorizontalScrollExtent()
{
return this.getWidth( );
}

@Override
protected int computeHorizontalScrollRange()
{
return fWorksheetWidth;
}

@Override
protected int computeHorizontalScrollOffset()
{
return this.getScrollX( );
}

@Override
protected int computeVerticalScrollExtent()
{
return this.getHeight( );
}

@Override
protected int computeVerticalScrollRange()
{
return fWorksheetHeight;
}

@Override
protected int computeVerticalScrollOffset()
{
return this.getScrollY( );
}

@Override
protected void onDraw(Canvas canvas)
{
canvas.drawColor( Color.BLACK );

Paint paint = new Paint( );

if ( fInteracting )
;

paint.setColor( Color.WHITE );
canvas.drawRect( 0, 0, fWorksheetWidth, fWorksheetHeight, paint );

paint.setColor( Color.RED );
for (int i = 0; i < 1500; i += 10)
{
canvas.drawLine( i, 0, i + 100, 500, paint );
}

canvas.drawRect( fWorksheetWidth - 50, 0, fWorksheetWidth, fWorksheetHeight, paint );
canvas.drawRect( 0, fWorksheetHeight - 50, fWorksheetWidth, fWorksheetHeight, paint );
}
}

关于android - 如何过度滚动自定义 View (surfaceview),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9334011/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com