Android: holder.getSurface() всегда возвращает ноль

Мой вид это куча нормальных виджетов и вид поверхности. Я не знаю, почему после того, как я получу surfaceholder SurfaceView и использование getSurface() снова на держателе, я всегда буду возвращать ноль.

Вот мой пример кода:

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.view);
    }

    @Override
    public void onResume() {
        super.onResume();
        surface = (SurfaceView) findViewById(R.id.surfaceView);
        this.holder = surface.getHolder();

         if (holder.getSurface().isValid()){  // get surface again
             Log.i("Notice","Surface holder is valid");
         }
         else
             Log.i("Notice","Surface holder ISNOT valid");  //Always receive this
        }

Когда я вижу документ Android для getSurface() метод. Вот как это говорит:

Прямой доступ к поверхности объекта. Поверхность может быть не всегда доступна - например, при использовании SurfaceView Поверхность держателя не создается до тех пор, пока вид не будет присоединен к диспетчеру окон и не выполнен макет, чтобы определить размеры и положение экрана Поверхности. Таким образом, вам обычно потребуется реализовать Callback.surfaceCreated, чтобы узнать, когда Surface доступен для использования.

Я не очень понимаю это, но знаю, что что-то упустил. Пожалуйста, объясните мне, и расскажите мне о Callback.surfaceCreated значит, а как это реализовать?

Спасибо:)

1 ответ

Решение

Вы пытаетесь использовать поверхность, когда она еще не доступна. Это нормально, это не доступно на вашем Activity.onCreate или же Activity.onResume методы, потому что на самом деле поверхность находится в отдельном окне позади вашего окна деятельности и имеет собственный жизненный цикл. Вам нужно реализовать SurfaceHolder.Callback, чтобы получать события о Surface Наличие и сделать рисунок из отдельной темы. Посмотрите на проект LunarLander в папке примеров Android SDK, там показано, как правильно использовать SurfaceView.

Ваш обратный вызов будет выглядеть примерно так:

public class MyCallback implements SurfaceHolder.Callback {
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, 
        int width, int height) {    
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // you need to start your drawing thread here
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {  
        // and here you need to stop it
    }
}

И чем вам нужно установить этот обратный вызов для SurfaceHolder:

surface.getHolder().addCallback(new MyCallback());

Я нашел решение, это сработало для меня, заразить ошибку в выборе правильного размера, поэтому при использовании MediaRecorder.setVideoSize() используйте этот метод, чтобы выбрать оптимальный размер

private static Size chooseOptimalSize(Size[] choices, int width, int height) {
        Size bigEnough = null;
        int minAreaDiff = Integer.MAX_VALUE;
        for (Size option : choices) {
            int diff = (width*height)-(option.getWidth()*option.getHeight()) ;
            if (diff >=0 && diff < minAreaDiff &&
                    option.getWidth() <= width &&
                    option.getHeight() <= height) {
                minAreaDiff = diff;
                bigEnough = option;
            }
        }
        if (bigEnough != null) {
            return bigEnough;
        } else {
            Arrays.sort(choices,new CompareSizeByArea());
            return choices[0];
        }

    }
Другие вопросы по тегам