【问题标题】:Custom view with a drawing thread prevents all views from displaying带有绘图线程的自定义视图可防止显示所有视图
【发布时间】:2015-06-19 17:09:56
【问题描述】:

我创建了一个自定义视图类并为其附加了一个线程。然后,我使用相应活动的 xml 布局文件添加了视图,其中还包含另一个视图,例如工具栏和文本视图。但是添加自定义视图时不显示视图;只是具有默认颜色的背景。没有错误。线程工作正常,我可以从调试日志中看到每一帧的时间差。但是,我看不出为什么没有显示任何视图。感谢您的帮助...

xml 布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:orientation="vertical"
    android:focusable="false">

    <android.support.v7.widget.Toolbar
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/toolbar"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        android:popupTheme="@style/ThemeOverlay.AppCompat.Light">
    </android.support.v7.widget.Toolbar>



    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
        android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".HomeActivity"
        android:orientation="vertical"
        android:id="@+id/background"
        android:focusable="false"
        android:animateLayoutChanges="true">

        <com.puppetlabs.canvastutorial.MyCanvasView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:id="@+id/mycanvasview"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="Large Text"
            android:id="@+id/textView" />

    </LinearLayout>

</LinearLayout>

自定义视图类:

package com.mert.canvastutorial;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * Created by Pc on 19.6.2015.
 */
public class MyCanvasView extends SurfaceView implements SurfaceHolder.Callback{

    private MyCanvasThread thread;

    private void init() {
        getHolder().addCallback(this);
        Log.d("SURFACE_VIEW", "Initialized.");
        // create the game loop thread
        thread = new MyCanvasThread(getHolder(),this);
        // make the GamePanel focusable so it can handle events
        setFocusable(true);
    }
    public MyCanvasView(Context context) {
        super(context);
        init();
    }

    public MyCanvasView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();

    }

    public MyCanvasView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

    }

    public void update(){

    }

    public void render(Canvas c){
        c.drawColor(Color.RED);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        //super.onDraw(canvas);
        //canvas.drawColor(Color.parseColor("#00dd00"));

    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        thread.setRunning(true);
        thread.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        boolean retry = true;
        while (retry) {
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {}
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }
}

而我对应的线程类是:

package com.mert.canvastutorial;

import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;

/**
 * Created by Pc on 19.6.2015.
 */
public class MyCanvasThread extends Thread {

    private final static int MAX_FPS = 30;
    private final static int MAX_FRAME_SKIPS = 5;

    private final static int FRAME_PERIOD = 1000/MAX_FPS;

    private SurfaceHolder surfaceHolder;
    private MyCanvasView myCanvasView;
    private boolean _run = false;

    public MyCanvasThread (SurfaceHolder surfaceHolder, MyCanvasView myCanvasView) {
        this.myCanvasView = myCanvasView;
        this.surfaceHolder = surfaceHolder;
        Log.d("THREAD","Initialized.");
    }

    public void setRunning (boolean _run) {
        this._run = _run;
    }

    @Override
    public void run() {
        //super.run();
        Canvas c;

        long beginTime;
        long timeDiff;
        int sleepTime;
        int framesSkipped;

        sleepTime = 0;

        while (_run) {
            c = null;

            try {
                c = surfaceHolder.lockCanvas(null);
                synchronized (surfaceHolder) {

                    beginTime = System.currentTimeMillis();
                    framesSkipped = 0;

                    myCanvasView.update();

                    myCanvasView.render(c);

                    timeDiff =  System.currentTimeMillis() - beginTime;
                    Log.d("TIME",String.valueOf(timeDiff));
                    sleepTime = (int) (FRAME_PERIOD - timeDiff);

                    if (sleepTime>0) {

                        try{
                            Thread.sleep(sleepTime);

                        } catch (InterruptedException e) {}
                    }

                    while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
                        this.myCanvasView.update();

                        sleepTime += FRAME_PERIOD;
                        framesSkipped++;
                    }

                }
            } finally {
                if (c!= null) {
                    surfaceHolder.unlockCanvasAndPost(c);
                }
            }
        }
    }
}

我将自定义视图从 xml 布局文件添加到活动中:

【问题讨论】:

    标签: android android-layout android-canvas surfaceview


    【解决方案1】:

    “自定义视图”不同于 SurfaceView 的子类化。 SurfaceView 有两个部分,Surface 和 View。如果你要在 View 部分上绘图,你想使用自定义 View,根本不需要 SurfaceView。 (有关此方法的更多信息,请参阅Creating Custom Views。)

    由于您尝试在 SurfaceView 的 Surface 上绘图,因此您可能不想覆盖 onDraw(),实际上您根本不需要将 SurfaceView 子类化。最佳做法是favor composition over inheritance

    SurfaceView 的 View 部分旨在成为一个透明的矩形,布局代码使用它在 View 层中留下一个“洞”。 SurfaceView Surface 位于一个单独的层上,默认情况下,它位于 View 层的后面。如果为 View 设置背景或在其上绘图,则会遮挡 Surface,并且什么都看不到。

    您可以通过在onCreate() 中使用setZOrderOnTop() 将SurfaceView 移到顶部来轻松确定是否是这种情况(创建Surface 后调用无效)。如果你这样做的时候你的Surface内容突然出现了,那么你的问题是你已经填写了SurfaceView的View部分。

    Grafika 中的“multi-surface test”活动演示了多个重叠 SurfaceView 上的动画 Canvas 渲染。

    FWIW,我建议您查看图形架构文档的 SurfaceView lifecyclegame loop 部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-19
      • 1970-01-01
      • 2019-12-12
      • 2012-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多