Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/217.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Android中平滑地滚动画布_Android_Android Canvas_Smooth Scrolling - Fatal编程技术网

在Android中平滑地滚动画布

在Android中平滑地滚动画布,android,android-canvas,smooth-scrolling,Android,Android Canvas,Smooth Scrolling,我不熟悉安卓系统 我正在视图的OnDraw(Canvas Canvas)方法内的画布上绘制位图、线条和形状。我正在寻找有关如何实现平滑滚动以响应用户拖动的帮助。我已经搜索了,但没有找到任何教程来帮助我 Canvas的参考似乎是说,如果画布是从位图(比如称为bmpBuffer)构建的,那么在画布上绘制的任何东西也会在bmpBuffer上绘制。是否可以使用bmpBuffer实现一个滚动。。。也许将它复制回画布,一次移动几个像素?但是,如果我使用Canvas.drawBitmap将bmpBuffer绘

我不熟悉安卓系统

我正在视图的OnDraw(Canvas Canvas)方法内的画布上绘制位图、线条和形状。我正在寻找有关如何实现平滑滚动以响应用户拖动的帮助。我已经搜索了,但没有找到任何教程来帮助我

Canvas的参考似乎是说,如果画布是从位图(比如称为bmpBuffer)构建的,那么在画布上绘制的任何东西也会在bmpBuffer上绘制。是否可以使用bmpBuffer实现一个滚动。。。也许将它复制回画布,一次移动几个像素?但是,如果我使用Canvas.drawBitmap将bmpBuffer绘制回画布,并将其偏移几个像素,bmpBuffer不会被损坏吗?因此,也许我应该将bmpBuffer复制到bmpBuffer2,然后将bmpBuffer2绘制回画布

更直接的方法是将线条、形状等直接绘制到缓冲区位图中,然后将缓冲区(通过移位)绘制到画布上,但就我所知,各种方法:drawLine()、drawShape()等都不可用于绘制位图。。。只在画布上

能给我两张画布吗?其中一个将从缓冲区位图构建,并仅用于绘制线条、形状等,然后将缓冲区位图绘制到另一个画布上以在视图中显示

我欢迎任何建议


这里(和其他网站上)对类似问题的回答是指“布告”。我理解这个概念,但在Android文档中找不到任何关于“blit”或“bitblt”的内容。是Canvas.drawBitmap和Bitmap.Copy Android的等价物吗?

我似乎找到了答案。我已经将大部分绘图代码(以前在onDraw()中)放入了一个新的doDrawing()方法中。此方法首先创建一个比屏幕大(大到足以容纳整个图形)的新位图。然后创建第二个画布,在其上进行详细绘制:

    BufferBitmap = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888);
    Canvas BufferCanvas = new Canvas(BufferBitmap);
doDrawing()方法的其余部分将用于绘制到BufferCanvas的详细图形

现在,整个onDraw()方法的内容如下:

    @Override protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawBitmap(BufferBitmap, (float) -posX, (float) -posY, null);
}
位置变量posX和posY在应用程序的onCreate()方法中初始化为0。应用程序实现OnTestureListener,并使用OnScroll通知中返回的distanceX和distanceY参数来增加posX和posY


这似乎就是实现平滑滚动所需的全部内容。还是我看得太多了

prepbgg:我认为代码不起作用,因为canvas.drawBitmap不会绘制到位图中,而是将位图绘制到画布上


如果我错了,请纠正我

我也有这个问题

我是这样画的:

Canvas BigCanvas = new Canvas();
Bitmap BigBitmap = new Bitmap(width,height);

int ScrollPosX , ScrollPosY  // (calculate these with the onScrollEvent handler)

void onCreate()
{
   BigCanvas.SetBitmap(BigBitmap);
}

onDraw(Canvas TargetCanvas)
{
   // do drawing stuff
   // ie.  BigCanvas.Draw.... line/bitmap/anything

   //draw to the screen with the scrolloffset

   //drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)
   TargetCanvas.DrawBitmap(BigBitmap(new Rect(ScrollPosX,ScrollPosY,ScrollPosX + BigBitmap.getWidth(),ScrollPosY + BigBitmap.getHeight(),new Rect(0,0,ScreenWidth,ScreenHeight),null);
}
对于平滑滚动,您需要在滚动后使用一些点(即第一个滚动点和第十个滚动点)的方法,减去这些点,然后在每个循环中滚动该数字,使其逐渐变慢(滚动量-圈数-摩擦)


我希望这能提供更多的见解。

无需重新启动活动!(根据prepbgg于2010年1月27日对其1月17日“答案”的回复)与其循环使用位图并导致重新加载活动的开销,不如将下面显示的“android:configChanges”属性放在应用程序的AndroidManifest.xml文件的“activity”元素中,以避免加载应用程序。这会告诉系统应用程序将处理方向更改,并且无需重新启动应用程序

<activity android:name=".ANote"
    android:label="@string/app_name"
    android:configChanges="orientation|screenLayout">
    <intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

继续回复维克多

事实上,情况更为复杂。因为抽签过程非常慢(在我那部缓慢的旧HTC Hero手机上需要2-3秒),我发现弹出一条吐司消息来告诉用户这是真的,并指出原因。显而易见的方法是创建一个只包含两行的新方法:

public void redrawBuffer(String strReason) {
    Toaster.Toast(strReason, "Short");`
    doDrawing();
}
并从程序中的其他位置调用此方法,而不是doDrawing()

然而,我发现烤面包机要么从未出现过,要么闪烁得如此短暂,以至于无法阅读。我的解决方法是使用时间检查处理程序强制程序在显示Toast和调用doDrawing()之间休眠200毫秒。虽然这稍微推迟了重新绘制的开始,但我觉得从程序的可用性来看,这是值得付出的代价,因为用户知道发生了什么。 reDrawBuffer()现在读取:

public void redrawBuffer(String strReason) {
    Toaster.Toast(strReason, "Short");
    mTimeCheckHandler.sleep(200);    
}`
处理程序代码(嵌套在我的视图类中)是:


今天早上在谷歌上多搜索了一点。根据这个网页,我可以有第二块画布,因此我将探讨这个想法。在下面的新“答案”中可以看到更多关于这个问题的信息。自从编写这个“答案”以来,我发现,当屏幕旋转时,需要额外的代码来“回收”缓冲区位图(和任何其他位图对象)。这是因为当屏幕旋转时,应用程序的主要活动结束并重新启动,但系统不会自动恢复位图对象使用的内存。因此,当不再需要位图时,为每个位图调用recycle()方法似乎很重要。对于缓冲区位图,答案似乎是覆盖活动的onDestroy方法,并在其中调用位图的recycle()。只需将
android:configChanges=“orientation”
放入清单中,即可避免此代码。参见Ribo于2011年1月4日对此问题的回答。请帮助回答此问题。卡马尔和怀尔德比尔,很抱歉,回答太慢。我最近没有看过这个帖子。我很高兴你解决了你的问题,卡马尔。在创建视图之后,我首先从主活动的onCreate()调用doDrawing();每当需要更改缓冲区位图中的图像时,我会再次调用doDrawing()。谢谢你的回复,Mervin。我不太清楚你的滚动是怎么工作的。你等我吗
public void redrawBuffer(String strReason) {
    Toaster.Toast(strReason, "Short");
    mTimeCheckHandler.sleep(200);    
}`
private timeCheckHandler mTimeCheckHandler = new timeCheckHandler();

class timeCheckHandler extends Handler {
@Override
    public void handleMessage(Message msg) {
        doDrawing();
    }
    public void sleep(long delayMillis) {
        this.removeMessages(0);
        sendMessageDelayed(obtainMessage(0), delayMillis);
    }
}`