I'm working an app that draws objects on SurfaceView
under some parameters, defined by the user. I created the layout for the app, which involves an header, footer, input (where user enters parameters to draw) and a custom SurfaceView
.
Here's the layout that simplified:
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Custom SurfaceView Layout -->
<org.firengine.myapp.CustomPreview
android:id="@+id/container_content"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- Header Layout: This is basically a Toolbar, with having a top padding of status bar height (see Note). -->
<FrameLayout
android:id="@+id/container_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/colorTint"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">...</FrameLayout>
<!-- Footer Layout - This is just a container, with having a bottom padding of navigation bar height (see Note). -->
<FrameLayout
android:id="@+id/container_footer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/colorTint"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">...</FrameLayout>
<!-- Input Layout - This is a empty container that shows views dynamically. -->
<LinearLayout
android:id="@+id/container_input"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="bottom|center_horizontal"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@+id/container_footer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/container_header" />
</android.support.constraint.ConstraintLayout>
The input layout generate dynamic views, based on parameters.
Suppose I create a EditText
inside input layout, so that the keyboard appears if you interact with that.
This is before the keyboard shows up.
This is when the keyboard is showing. Notice that the app layout is panned and the header layout got invisible.
The problem occurs when the keyboard goes down. The header layout, which is invisible earlier, stays invisible all the time (until the user interacts with the app).
I turned on GPU overdraw to check the problem (also setting SurfaceView
background color to white), and here is the result.
Before:
After:
Also, here's my custom SurfaceView
class (I think that the custom SurfaceView
is blocking the UI thread to draw the layouts that disappeared).
public class CustomPreview extends SurfaceView implements SurfaceHolder.Callback {
private final Handler handler = new Handler();
private final Runnable runnable = new Runnable() {
@Override
public void run() {
draw();
}
};
private Renderer renderer;
private boolean visible;
private boolean canLoadData;
private HashMap<String, String> data;
public CustomPreview(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
getHolder().setFormat(PixelFormat.RGBA_8888);
visible = false;
canLoadData = false;
renderer= new Renderer(context);
data = new HashMap<>();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
visible = true;
refreshHandler(0);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
renderer.updateDimensions(width, height);
canLoadData = true;
renderer.updateData(data);
refreshHandler(0);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
renderer.clearData();
visible = false;
canLoadData = false;
refreshHandler(0);
}
public void setVisibility(boolean visible) {
this.visible = visible;
refreshHandler(0);
}
private void draw() {
Canvas canvas = null;
try {
canvas = getHolder().lockCanvas();
if (canvas != null) {
renderer.draw(canvas);
}
} finally {
if (canvas != null) {
getHolder().unlockCanvasAndPost(canvas);
}
}
refreshHandler(60000);
}
public void saveData(String key, String value) {
data.put(key, value);
if (canLoadData) {
renderer.updateData(data);
}
refreshHandler(0);
}
private void refreshHandler(long delay) {
handler.removeCallbacks(runnable);
if (visible) {
if (delay > 0) {
handler.postDelayed(runnable, delay);
} else {
handler.post(runnable);
}
}
}
public String loadData(String key) {
return data.get(key);
}
Am I doing something wrong? If so, can someone explain what it is?
I'm glad if someone helps me out. Thank you.
Note: Heres some extra information about the layout.
AdView
, which is not included in the layout.SYSTEM_UI_FLAG_HIDE_NAVIGATION
and SYSTEM_UI_FLAG_FULLSCREEN
flags was added to the activity and because of that, paddings were set in respective layouts to avoid overlapping.Try following in the Manifest
android:windowSoftInputMode="adjustNothing"
<activity
android:name=".app.main.MainActivity"
android:windowSoftInputMode="adjustNothing">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With