2013-04-09 18 views
10

Ich brauche etwas Hilfe beim Verständnis der Grundlagen des Scrollens über Elemente, die auf einer Leinwand in Android gezeichnet werden. Angenommen, ich möchte eine Zeitachse erstellen, in der die Zeit bei 0 der Anfang einer Visualisierung ist und die Zeitachse im Laufe der Zeit weiter unter dem vorherigen Punkt dargestellt wird. Wenn ich dies auf Android rendern möchte, weiß ich, dass ich einfach eine Reihe von Elementen auf einer Leinwand erstellen kann, indem ich onDraw() überschreibe. Nehmen wir jedoch an, die Visualisierung ist größer als der Bildschirm erlaubt.Scrollen über große Leinwand

Zum Beispiel im ersten Bild unten enthält die große schwarze Box die gesamte Leinwand, wie ich es rendere. Ich erstelle eine blaue Linie, die senkrecht nach oben und unten verläuft, sowie mehrere gelbe, grüne und blaue Rechtecke. Das rote Kästchen stellt den Bildschirm des Android dar, der die Visualisierung rendert. Beim ersten Öffnen werden alle Objekte gezeichnet, aber nur die Elemente, die in der roten Box enthalten sind, werden auf dem Bildschirm angezeigt.

Before_Scroll

Nun, wenn der Benutzer nach unten zu rollen ist, Gegenstände, die zunächst unter dem roten Kasten erschienen sind in Aussicht, während Gegenstände, die nicht aus den Grenzen des roten Feldes gegangen sind länger sichtbar sind, wie dargestellt in das zweite Bild.

After_Scroll

Ich glaube, ich brauche scrollables zu verwenden, aber ich bin ganz verloren, wie dies zu tun. Ich habe diese Seite http://developer.android.com/training/custom-views/custom-drawing.html gelesen und erklärt, wie man eigene Kundenbilder erstellt und diese Seite http://developer.android.com/training/custom-views/making-interactive.html erklärt, wie man die UI interaktiv macht, aber ich denke, dass mir etwas fehlt.

Ein Beispielcode, der dieses Problem veranschaulicht (dies ist einfach, annehmen, dass es logisch Diktieren, wo die Boxen/Linien gehen, etc.) ist wie folgt:

package com.example.scrolltest; 

import com.example.scrolltest.Draw; 

import android.os.Bundle; 
import android.app.Activity; 
import android.graphics.Color; 

public class MainActivity extends Activity { 
    Draw draw; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

    draw = new Draw(this); 
    draw.setBackgroundColor(Color.WHITE); 
    setContentView(draw); 
    } 
} 

und

package com.example.scrolltest; 


import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.view.View; 


public class Draw extends View { 
    Paint paint = new Paint(); 

    public Draw(Context context) { 
     super(context);    
    } 

    @Override 
    public void onDraw(Canvas canvas) { 

     paint.setColor(Color.GREEN); 
     canvas.drawRect(30, 30, 90, 200, paint); 
     paint.setColor(Color.BLUE); 

     canvas.drawLine(100, 20, 100, 1900, paint); 

     paint.setColor(Color.GREEN); 
     canvas.drawRect(200, 2000, 400, 3000, paint); 
     } 
} 

Was ich jedoch nicht herausfinden kann, ist, wie ich mit einem scrollbaren Bild zu den Rechtecken scrollen kann, die sich außerhalb des Bildschirms befinden. Ich bin mir auch nicht sicher, ob ich das richtig begonnen habe oder stattdessen Zeichen verwenden sollte ...

Antwort

20

Einfache Methode (wenn die erforderliche Höhe nicht sehr groß ist).

Verwenden Sie eine ScrollView und fügen Sie Ihre Draw-Ansicht darin hinzu. Berechnen Sie die erforderliche Höhe für diese Ansicht in onMeasure.

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

draw = new Draw(this); 
draw.setBackgroundColor(Color.WHITE); 
ScrollView scrollView = new ScrollView(this); 
scrollView.addView(draw); 
setContentView(scrollView); 
} 

public class Draw extends View { 
     Paint paint = new Paint(); 

     public Draw(Context context) { 
      super(context);    
     } 

     @Override 
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
      // Compute the height required to render the view 
      // Assume Width will always be MATCH_PARENT. 
      int width = MeasureSpec.getSize(widthMeasureSpec); 
      int height = 3000 + 50; // Since 3000 is bottom of last Rect to be drawn added and 50 for padding. 
      setMeasuredDimension(width, height); 
     } 

     @Override 
     public void onDraw(Canvas canvas) { 

      paint.setColor(Color.GREEN); 
      canvas.drawRect(30, 30, 90, 200, paint); 
      paint.setColor(Color.BLUE); 

      canvas.drawLine(100, 20, 100, 1900, paint); 

      paint.setColor(Color.GREEN); 
      canvas.drawRect(200, 2000, 400, 3000, paint); 
      } 
    } 
+0

wie können wir Feature auf die Leinwand add Panning? –

0

Eine Alternative kann die Verwendung von Offset-X/Y-Werten sein.

Wie Sie mit den Offset-Werten umgehen, bleibt Ihnen überlassen, obwohl ich lieber einen Klasse-I-Aufruf Camera verwende. Der Zugriff sollte statisch sein.

public void render(Canvas c){ 
    c.drawRect(100 - offsetX, 100 - offsetY, 120 - offsetX, 120 - offsetY, Paints.BLUE); 

} 

Und die Leinwand zu schwenken:

float x, y; 
@Override 
public boolean onTouchEvent(MotionEvent ev) { 
    if(ev.getAction() == MotionEvent.ACTION_DOWN){ 
     x = ev.getX(); 
     y = ev.getY(); 
    }else if (ev.getAction() == MotionEvent.ACTION_MOVE) { 
     float currX = ev.getX(); 
     float currY = ev.getY(); 

     float newOffsetX = (x - currX), 
       newOffsetY = (y - currY); 
     //The next two if-statements are to add sensitivity to the scrolling. 
     //You can drop these if you don't plan on having touch events 
     //with pressing. Pressing works without this as well, but the canvas may move slightly 
     //I use DP to handle different screen sizes but it can be replaced with pixels. c is a context-instance 
     if (newOffsetY < Maths.convertDpToPixel(2, c) && newOffsetY > -Maths.convertDpToPixel(2, c)) 
      newOffsetY = 0; 

     if (newOffsetX < Maths.convertDpToPixel(2, c) && newOffsetX > -Maths.convertDpToPixel(2, c)) 
      newOffsetX = 0; 
     offsetX += newOffsetX; 
     offsetY += newOffsetY; 
     x = ev.getX(); 
     y = ev.getY(); 
    } 

    return true; 

} 

und eine Kamera-Klasse Beispiel:

public class Camera{ 

    public static float offsetX, offsetY; 
    //The constructor. ix and iy is the initial offset. Useful if you are creating a game and need to change the initial offset to center around a starting position. 
    //Most of the time it will be enough to set the values to 0 
    public Camera(float ix, float iy){ 
     this.offsetX = ix; 
     this.offsetY = iy; 
    } 

} 
Verwandte Themen