2013-04-09 93 views
10

我需要一些帮助来理解在Android中绘制到画布上的项目时滚动的基础。假设我想创建一个时间轴,其中0的时间是可视化的顶部,随着时间的增加,时间轴继续呈现在先前点的下方。如果我想在Android上渲染,我知道我可以简单地通过覆盖onDraw()在画布上创建一堆项目。但是,让我们假设可视化比屏幕允许的更大。在大型画布上滚动

例如,在下面的第一张图片中,大黑盒包含整个画布,因为我呈现它。我创建了一条垂直向上和向下运行的蓝线以及几个黄色,绿色和蓝色矩形。红色框表示正在渲染可视化的Android屏幕。当它最初打开时,所有项目都被绘制,但只有红色框中包含的项目出现在屏幕上。

Before_Scroll

现在,如果用户向下滚动,最初出现下面的红框中的项目在视野中,而已经没有了红色框的范围的项目不再visable,作为代表第二张照片。

After_Scroll

我相信我需要使用scrollables但我很丢了怎么办等等。我已阅读此页http://developer.android.com/training/custom-views/custom-drawing.html解释如何创建您自己的客户图像和此页面http://developer.android.com/training/custom-views/making-interactive.html解释如何使UI交互,但我认为我错过了一些东西。

示出该问题的示例代码(这是基本的,假定有逻辑口述WHERE的框/线去等)如下:

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

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

但我无法弄清楚的是,我如何使用滚动条向下滚动到屏幕外的矩形。我也不确定,如果我开始正确或应该使用drawables,而不是...

回答

20

简单的方法(如果所需的高度不是很大)。

使用ScrollView并在其中添加您的绘制视图。在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

怎样才能加平移功能画布? – 2016-04-26 13:11:59

0

另一种方法是使用偏移量X/Y值。

您如何处理偏移值取决于您,尽管我更喜欢使用我称之为Camera的类。访问应该是静态的。

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

} 

而要平移画布:

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; 

} 

和样本相机类:

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

}