2012-02-17 4 views
5

У меня есть пользовательский SurfaceView, который управляется рабочим потоком. Я использую код очень похож на код в следующем блоге управлять SurfaceView:Как прокрутить пользовательский вид (обзор поверхности)

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

Мой заказ SurfaceView прокручивать в том смысле, что я слушаю сенсорных событий, отправить их на детектор жест, и реализовать onScroll. Я отслеживаю расстояния прокрутки в некоторых переменных-членах (как по оси x, так и по оси Y) и переводит любые координаты на соответствующие суммы при рисовании на холст. Я также зажимаю расстояние прокрутки и могу легко вычислять и хранить любые суммы перескакивания при зажатии.

Все это работает нормально.

Проблема в том, что я хочу показать стандартные эффекты скроллинга Android на моем пользовательском SurfaceView. Я попытался вызвать overScrollBy вручную, но это не сработало, и я полагаю, что я рисую представление из рабочего потока, что означает, что onDraw никогда не вызывается.

Я нашел следующий StackOverflow пост о настройке overscroll эффектов:

How can I change the OverScroll color in Android 2.3.1?

Это сообщение не предназначено для SurfaceViews, но я мог бы адаптировать код. Тем не менее, есть ли лучший способ? Я хочу показать тот же самый эффект сверхсброса, который показан в другом месте. Создание копий чертежей перепрограммирования и попытка дублирования логики перемотки кажется ... уродливой.

ответ

0

Ну, у меня точно такая же проблема.

Я посмотрел на реализацию вида андроида, и внутри «onOverScrolled» есть только комментарий «Умышленно пустой».

Глядя на реализацию ListView, я вижу, что они внедрили ее вручную, получив drawables 'com.android.internal.R.styleable.ListView_overScrollHeader' и 'com.android.internal.R.styleable.ListView_overScrollFooter ', которые нельзя использовать извне. К сожалению, я не смог найти эти ресурсы в источниках.

, как это кажется нам придется делать вручную overscroll ...

4

Ну, я сумел собрать простой пример overscroll простого вида с помощью OverScroller:

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

Ok, чтобы действительно ответить на вопрос о стиле прокрутки в стиле Android. Вы можете сделать шаг дальше, чем мой последний ответ (код). После использования OverScroller для реализации чрезмерной прокрутки по чертежу вы можете ограничить перемещение страницы, чтобы страница не перескакивала. Вместо этого вы можете нарисовать ресурс для прокрутки стиля Android - и это то, что вы называете «ручным».

См. Образец ниже, который в дополнение к коду, который я опубликовал вчера. Теперь «onDraw» не позволит странице визуально перескакивать. Затем «moveatchDraw» будет рисовать ресурс, пригодный для воспроизведения, для представления прокрутки в стиле Android.

Обратите внимание, что я уродка памяти, поэтому я использую один и тот же ресурс для всех четырех углов и поворачиваю его вручную через матрицы при рендеринге на холсте.

private void compensateForOverscroll(Canvas canvas) 
    { 
     int x = this.getScrollX(); 
     int y = this.getScrollY(); 

     Matrix matrix = canvas.getMatrix(); 

     int maxX = fWorksheetWidth - this.getWidth(); 
     int maxY = fWorksheetHeight - this.getHeight(); 

     if (x < 0 || x > maxX || y < 0 || y > maxY) 
     { 
      if (x < 0) 
       matrix.postTranslate(x, 0); 
      else if (x > maxX) 
       matrix.postTranslate((x - maxX), 0); 

      if (y < 0) 
       matrix.postTranslate(0, y); 
      else if (y > maxY) 
       matrix.postTranslate(0, (y - maxY)); 

      canvas.setMatrix(matrix); 
     } 
    } 

    @Override 
    protected void dispatchDraw(Canvas canvas) 
    { 
     int width = this.getWidth(); 
     int height = this.getHeight(); 
     int maxX = fWorksheetWidth - width; 
     int maxY = fWorksheetHeight - height; 

     int x = this.getScrollX(); 
     int y = this.getScrollY(); 


     if (x < 0 || x > maxX) 
     { 
      canvas.save(); 
      Matrix canvasMatrix = canvas.getMatrix(); 

      if (x < 0) 
      { 
       fOverScrollDrawable.setBounds(0, x, height, x - x); 
       canvasMatrix.preRotate(-90); 
       canvasMatrix.preTranslate(- y - height, 0); 
      } 
      else if (x > maxX) 
      { 
       fOverScrollDrawable.setBounds(0, maxX, height, x); 
       canvasMatrix.preRotate(90); 
       canvasMatrix.preTranslate(y, - x - fWorksheetWidth); 
      } 

      canvas.setMatrix(canvasMatrix); 
      fOverScrollDrawable.draw(canvas); 

      canvas.restore(); 
     } 

     if (y < 0 || y > maxY) 
     { 
      canvas.save(); 
      Matrix canvasMatrix = canvas.getMatrix(); 

      if (y < 0) 
      { 
       fOverScrollDrawable.setBounds(x, y, x + width, y - y); 
      } 
      else if (y > maxY) 
      { 
       fOverScrollDrawable.setBounds(0, maxY, width, y); 
       canvasMatrix.preRotate(180); 
       canvasMatrix.preTranslate(- x - width, - y - fWorksheetHeight); 
      } 

      canvas.setMatrix(canvasMatrix); 
      fOverScrollDrawable.draw(canvas); 

      canvas.restore(); 
     } 
    } 

    @Override 
    protected void onDraw(Canvas canvas) 
    { 
     canvas.save(); 

     this.compensateForOverscroll(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); 

     canvas.restore(); 
    } 

вытяжка инициализируется так:

Drawable fOverScrollDrawable; 

... 

Resources rsr = context.getResources(); 
fOverScrollDrawable = rsr.getDrawable(R.drawable.overscroll_glow); 

Ресурс изображения для overscroll свечения, я взял два изображения в сочетании и SDK их в единую вытяжке ресурса:

  • \ Android-SDK \ \ платформ Android, 11 \ Data \ Реза \ вытяжка-ИПЧР \ overscroll_edge.png
  • \ Android-SDK \ \ платформ Android, 11 \ Data \ Реза \ Drawable -hdpi \ overscroll_glow.png
Смежные вопросы