2015-06-19 2 views
0

Я создал пользовательский класс представления и привязал к нему поток. Затем я добавил представление, используя файл макета 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:

ответ

0

«Пользовательский вид» отличается от подкласса SurfaceView. SurfaceView имеет две части: поверхность и вид. Если вы собираетесь рисовать на части просмотра, вы хотите использовать пользовательский вид, и вообще нет необходимости иметь SurfaceView. (См Creating Custom Views больше об этом подходе.)

Поскольку вы пытаетесь рисовать на поверхности SurfaceView, вы, вероятно, не хотите, чтобы переопределить onDraw(), а на самом деле вам не нужно подкласс SurfaceView в все. Наилучшая практика - favor composition over inheritance.

View the SurfaceView предназначен для того, чтобы быть прозрачным прямоугольником, который использует код макета, чтобы оставить «отверстие» в слое «Вид». SurfaceView Surface находится на отдельном слое, который по умолчанию находится за слоем «Вид». Если вы установите фон для представления или нарисуете его, вы закроете поверхность и не сможете ничего увидеть.

Вы можете тривиально определить, может ли это быть выполнено, перемещая SurfaceView сверху, используя setZOrderOnTop() в onCreate() (вызов не действует после того, как поверхность была создана). Если ваш контент Surface неожиданно появится, когда вы это сделаете, ваша проблема в том, что вы заполнили часть View SurfaceView.

Активность «multi-surface test» в Графике демонстрирует анимированную визуализацию холста на нескольких перекрывающихся поверхностных изображениях.

FWIW, я бы порекомендовал посмотреть разделы SurfaceView lifecycle и game loop графической архитектуры doc.

Смежные вопросы