问题
Problem
The activity layout has a DrawerLayout
with a FrameLayout
as content to Fragment
and a LinearLayout
to be opened and closed by drawer. The fragment used on content has a FrameLayout
with fitsSystemWindows
flag and a Toolbar
.
If I insert the fragment at onCreate()
all occurs as expected, the FrameLayout
starts on position 0 and the Toolbar
starts below the statusbar. But outside the onCreate()
the same code fails, the fitsSystemWindows
not works with FrameLayout
.
An important point, I need the Toolbar
and fitsSystemWindows
flag on Fragment
and not on Activity
.
How to get the same behavior seen at onCreate()
moment?
Code
Main Activity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
window.setStatusBarColor(Color.TRANSPARENT);
}
setContentView(R.layout.activity);
findViewById(R.id.item).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Out of onCreate fails
replaceFragment();
}
});
// With onCreate all OK
replaceFragment();
}
private void replaceFragment() {
getSupportFragmentManager().beginTransaction()
.replace(R.id.content, new MainFragment())
.commit();
}
}
Main Layout
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer"
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">
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<LinearLayout
android:layout_width="256dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#ff0000"
android:orientation="vertical"
tools:layout_gravity="">
<View
android:layout_width="match_parent"
android:layout_height="168dp"
android:layout_marginBottom="16dp"
android:background="#00ffff"/>
<TextView
android:id="@+id/item"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#ff00ff"
android:gravity="center"
android:text="Click me"/>
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
Fragment
public class MainFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment, container, false);
}
}
Fragment layout:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#00ff00"
android:fitsSystemWindows="true">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="#0000ff"/>
</FrameLayout>
</RelativeLayout>
Example
The LinearLayout
to be opened is in red. The FrameLayout
with the fitsSystemWindows
flag is in green and the toolbar is in blue, the cyan view is working all the time, it need start at y position 0. The expected is Green and blue like the first time, but in the second time the blue is the unique viewed.
回答1:
So, the problem is, that the when the content is being changed, system will no longer dispatch those insets to the view hierarchy.
This can be easily solved with ViewCompat.requestApplyInsets(View) API. That would force the system to dispatch WindowInsets
once again.
Ask that a new dispatch of
View.onApplyWindowInsets(WindowInsets)
be performed. This falls back toView.requestFitSystemWindows()
where available.
So, in your example performing this changes would result in expected behavior:
private void replaceFragment() {
getSupportFragmentManager().beginTransaction()
.replace(R.id.content, new MainFragment())
// NOTE, we are performing `commitNow()` instead of ordinary `commit()`,
// Because we want this commit to happen sychronously/immediately
.commitNow();
// Ask the framework to dispatch window insets once more to the root of your view hierarchy
ViewCompat.requestApplyInsets(findViewById(R.id.drawer));
}
来源:https://stackoverflow.com/questions/35799876/fitssystemwindows-on-fragment-activity-and-drawerlayout-combination