問題
以下のようなコードを実行して、ボタンをタップすると画面が点滅する。
MainActivity.java
package com.hkurokawa.myapplication;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MainActivity extends AppCompatActivity {
ViewGroup content;
View dummy;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
content = (ViewGroup) findViewById(R.id.content);
dummy = LayoutInflater.from(this).inflate(R.layout.view_dummy, content, false);
}
public void onBtnClick(View view) {
content.removeAllViews();
content.addView(dummy);
}
}
activity_main.xml
<RelativeLayout 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"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onBtnClick"
android:text="Add SurfaceView" />
<FrameLayout
android:id="@+id/content"
android:layout_below="@id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</FrameLayout>
</RelativeLayout>
view_dummy.xml
<?xml version="1.0" encoding="utf-8"?>
<SurfaceView xmlns:android="http://schemas.android.com/apk/res/android"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"/
調査
調べて分かったこと。
- 初回のみ起きる。2回目以降の
addView
では点滅しない。 -
addView
のタイミングで起きる。デバッガで追ったところ、addView
メソッドを抜けてから点滅するので、どこかで View Hierarchy を監視していて、SurfaceView
が追加されたときに何かやっているのかもしれない。 -
addView
がonCreate
メソッド内であれば点滅はしない。 -
SurfaceView
が含まれるFargment
を表示するのでも同じ。内部的にaddView
が呼ばれるので。 - 追加する
SurfaceView
が一瞬見えているのかと思ったけれど、そうではない模様。上の例でもvisibility="gone"
だけれども点滅する。背景色を変えてもダメ。
解決
以下のように幅と高さが 0dp
の SurfaceView
を activity_main.xml
に含めておけば回避できる。
activity_main.xml
<RelativeLayout 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"
tools:context=".MainActivity">
<!-- Somehow, if you add a SurfaceView in advance, the screen does not blink. -->
<SurfaceView
android:layout_width="0dp"
android:layout_height="0dp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onBtnClick"
android:text="Add SurfaceView" />
<FrameLayout
android:id="@+id/content"
android:layout_below="@id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</FrameLayout>
</RelativeLayout>
StackOverflow にも同様の解決方法が載っていた。Surface
が初めて足されたタイミングで IWindowSession#relayout()
が呼ばれるらしく、それが点滅の原因とのこと。