2012-02-17 11 views
5

मेरे पास एक कस्टम SurfaceView है जिसे वर्कर थ्रेड द्वारा प्रबंधित किया जाता है। मैं SurfaceView प्रबंधन करने के लिए बहुत निम्न ब्लॉग पोस्ट में कोड के समान कोड का उपयोग कर रहा:कस्टम व्यू को ओवरक्रॉल कैसे करें (सतहदृश्य)

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

मेरे कस्टम SurfaceView अर्थ है कि मैं स्पर्श घटनाओं के लिए सुनने में स्क्रॉल करने योग्य है, उन्हें एक इशारा डिटेक्टर को भेजें, और स्क्रॉल पर लागू करें। मैं कुछ सदस्य चर (दोनों एक्स-अक्ष और वाई-अक्ष) में स्क्रॉल दूरी का ट्रैक रखता हूं और कैनवास पर चित्रित करते समय उचित मात्रा में किसी भी निर्देशांक का अनुवाद करता हूं। मैं स्क्रॉल दूरी को भी दबाता हूं और क्लैंपिंग के दौरान आसानी से गणना और स्टोर कर सकता हूं।

यह सब ठीक काम करता है।

समस्या यह है कि मैं अपने कस्टम SurfaceView पर मानक एंड्रॉइड ओवरक्रॉल प्रभाव दिखाना चाहता हूं। मैंने मैन्युअल रूप से स्क्रॉलबॉई को कॉल करने का प्रयास किया लेकिन यह काम नहीं किया और मेरा सबसे अच्छा अनुमान यह है कि मैं एक कार्यकर्ता थ्रेड से दृश्य खींच रहा हूं जिसका अर्थ है कि व्यू ऑन ऑन ड्रा को कभी नहीं कहा जाता है।

मैं ओवरस्क्रॉल प्रभाव अनुकूलित करने के बारे निम्नलिखित stackoverflow पोस्ट पाया:

How can I change the OverScroll color in Android 2.3.1?

पद SurfaceViews लिए लक्षित नहीं है यही कारण है कि, लेकिन मैं शायद कोड अनुकूलन कर सकते हैं। उस ने कहा, क्या कोई बेहतर तरीका है? मैं सटीक उसी overscroll प्रभाव दिखाना चाहता हूं जो कहीं और दिखाए जाते हैं। Overscroll drawables की प्रतियां बनाना और overscroll तर्क को डुप्लिकेट करने का प्रयास लगता है ... बदसूरत।

उत्तर

0

ठीक है, मेरे पास वही समस्या है।

मैंने एंड्रॉइड व्यू के कार्यान्वयन को देखा, और 'ऑन ओवरस्क्रॉल' के अंदर केवल "जानबूझकर खाली" टिप्पणी है।

ListView कार्यान्वयन को देखते हुए, मैं देख सकता हूँ मैन्युअल ड्रॉएबल 'com.android.internal.R.styleable.ListView_overScrollHeader' और 'com.android.internal.R.styleable.ListView_overScrollFooter हो रही द्वारा है कि वे इसे क्रियान्वित किया है 'जो बाहर से इस्तेमाल नहीं किया जा सकता है। दुर्भाग्यवश, मैं उन संसाधनों को स्रोतों में नहीं ढूंढ पाया।

ऐसा लगता है के रूप में हम ओवरस्क्रॉल मैन्युअल करना होगा ...

4

ठीक है, मैं 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

ठीक है, वास्तव में एंड्रॉइड स्टाइल overscroll के सवाल का जवाब देने के लिए। आप मेरे अंतिम उत्तर (कोड) से एक कदम आगे जा सकते हैं ड्राइंग के माध्यम से ओवरक्रॉलिंग को लागू करने के लिए ओवरस्क्रॉलर का उपयोग करने के बाद, आप पृष्ठ आंदोलन को प्रतिबंधित कर सकते हैं, इसलिए पृष्ठ overscroll नहीं होगा। इसके बजाय, आप एंड्रॉइड स्टाइल overscroll के लिए संसाधन आकर्षित कर सकते हैं - और यही वह है जिसे आप 'मैन्युअल' कहते हैं।

नीचे दिए गए नमूने को देखें, जो कल मैंने पोस्ट किए गए कोड के अतिरिक्त है। अब, 'ऑनड्रा' पृष्ठ को दृष्टि से overscroll नहीं होने देगा। फिर 'डिसप्लेच ड्रा' एंड्रॉइड स्टाइल ओवरक्रॉल का प्रतिनिधित्व करने के लिए एक ड्रॉबल संसाधन तैयार करेगा।

नोट, मैं एक मेमोरी सनकी हूं, इसलिए मैं सभी चार कोनों के लिए एक ही संसाधन का उपयोग करता हूं और कैनवास पर प्रतिपादन करते समय इसे मैट्रिक्स के माध्यम से मैन्युअल रूप से घुमाता हूं।

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 ऐसे ही आरंभ नहीं हो जाता:

:

Drawable fOverScrollDrawable; 

... 

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

ओवरस्क्रॉल चमक के लिए छवि संसाधन, मैं एक भी drawable संसाधन में SDK में दो छवियों लिया और उन्हें संयोजित कर दी है

  • \ Android-SDK \ प्लेटफार्मों \ एंड्रॉयड-11 \ डेटा \ रेस \ drawable-hdpi \ overscroll_edge.png
  • \ Android-SDK \ प्लेटफार्मों \ एंड्रॉयड-11 \ डेटा \ रेस \ drawable -hdpi \ overscroll_glow.png
संबंधित मुद्दे