From 3d71e0827201861aece51b88d4ccbb1d8df80681 Mon Sep 17 00:00:00 2001 From: seven332 Date: Sat, 28 Feb 2015 15:52:04 +0800 Subject: [PATCH] Update --- .../com/hippo/ehviewer/EhApplication.java | 5 +- .../com/hippo/ehviewer/client/ListParser.java | 7 +- .../hippo/ehviewer/ui/ContentActivity.java | 17 +- .../ehviewer/ui/fragment/SearchFragment.java | 11 +- .../ehviewer/ui/scene/GalleryDetailScene.java | 20 - .../ehviewer/ui/scene/GalleryListScene.java | 27 +- .../hippo/ehviewer/widget/ContentLayout.java | 91 +++++ .../ehviewer/widget/GalleryListView.java | 19 + .../hippo/ehviewer/widget/SearchLayout.java | 9 + .../main/java/com/hippo/scene/Announcer.java | 356 ++++++++++++++++++ .../main/java/com/hippo/scene/Curtain.java | 19 + app/src/main/java/com/hippo/scene/Scene.java | 175 ++++++--- .../com/hippo/scene/SceneApplication.java | 34 ++ .../java/com/hippo/scene/SceneManager.java | 120 ++++++ .../java/com/hippo/scene/StageActivity.java | 191 ++-------- .../java/com/hippo/scene/StageLayout.java | 6 +- ...tEqualsException.java => AssertError.java} | 4 +- .../java/com/hippo/util/AssertException.java | 23 ++ .../main/java/com/hippo/util/AssertUtils.java | 27 +- .../com/hippo/widget/DrawerFrameLayout.java | 29 +- app/src/main/res/layout/activity_content.xml | 5 +- 21 files changed, 919 insertions(+), 276 deletions(-) create mode 100644 app/src/main/java/com/hippo/ehviewer/widget/ContentLayout.java create mode 100644 app/src/main/java/com/hippo/ehviewer/widget/GalleryListView.java create mode 100644 app/src/main/java/com/hippo/scene/Announcer.java create mode 100644 app/src/main/java/com/hippo/scene/Curtain.java create mode 100644 app/src/main/java/com/hippo/scene/SceneApplication.java create mode 100644 app/src/main/java/com/hippo/scene/SceneManager.java rename app/src/main/java/com/hippo/util/{NotEqualsException.java => AssertError.java} (84%) create mode 100644 app/src/main/java/com/hippo/util/AssertException.java diff --git a/app/src/main/java/com/hippo/ehviewer/EhApplication.java b/app/src/main/java/com/hippo/ehviewer/EhApplication.java index e87117938..ab76516a3 100644 --- a/app/src/main/java/com/hippo/ehviewer/EhApplication.java +++ b/app/src/main/java/com/hippo/ehviewer/EhApplication.java @@ -15,11 +15,10 @@ package com.hippo.ehviewer; -import android.app.Application; - +import com.hippo.scene.SceneApplication; import com.hippo.util.UiUtils; -public class EhApplication extends Application { +public class EhApplication extends SceneApplication { @Override public void onCreate() { diff --git a/app/src/main/java/com/hippo/ehviewer/client/ListParser.java b/app/src/main/java/com/hippo/ehviewer/client/ListParser.java index 429d7ee4a..99a894e9a 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/ListParser.java +++ b/app/src/main/java/com/hippo/ehviewer/client/ListParser.java @@ -18,8 +18,8 @@ package com.hippo.ehviewer.client; import com.hippo.ehviewer.data.GalleryInfo; import com.hippo.ehviewer.data.LofiGalleryInfo; import com.hippo.ehviewer.util.EhUtils; +import com.hippo.util.AssertException; import com.hippo.util.AssertUtils; -import com.hippo.util.NotEqualsException; import com.hippo.util.Utils; import java.util.ArrayList; @@ -224,10 +224,9 @@ public class ListParser { private static final String PAU_SPACER = " by "; - private void getPostedAndUploader(String raw, String[] pau) - throws NotEqualsException { + private void getPostedAndUploader(String raw, String[] pau) throws AssertException { int index = raw.indexOf(PAU_SPACER); - AssertUtils.assertEquals("Can not parse posted and uploader", index, -1); + AssertUtils.assertEqualsEx("Can not parse posted and uploader", index, -1); pau[0] = raw.substring(0, index); pau[1] = raw.substring(index + PAU_SPACER.length()); } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java index 18deb08f2..4024d6716 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java @@ -21,6 +21,7 @@ import android.support.v4.widget.DrawerLayout; import com.hippo.ehviewer.R; import com.hippo.ehviewer.ui.scene.GalleryListScene; +import com.hippo.ehviewer.widget.ContentLayout; import com.hippo.scene.StageActivity; import com.hippo.scene.StageLayout; @@ -29,7 +30,7 @@ public class ContentActivity extends StageActivity { private Resources mResources; private DrawerLayout mDrawerLayout; - private StageLayout mStage; + private ContentLayout mContentLayout; @Override protected void onCreate(Bundle savedInstanceState) { @@ -39,15 +40,21 @@ public class ContentActivity extends StageActivity { mResources = getResources(); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout); - mStage = (StageLayout) mDrawerLayout.findViewById(R.id.stage); + mContentLayout = (ContentLayout) mDrawerLayout.findViewById(R.id.stage); mDrawerLayout.setStatusBarBackground(R.color.theme_primary_dark); - startFirstScene(GalleryListScene.class); + if (savedInstanceState == null) { + startScene(GalleryListScene.class, null); + } + } + + public int getFitPaddingBottom() { + return mContentLayout.getFitPaddingBottom(); } @Override - public StageLayout getStageView() { - return mStage; + public StageLayout getStageLayout() { + return mContentLayout; } } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/fragment/SearchFragment.java b/app/src/main/java/com/hippo/ehviewer/ui/fragment/SearchFragment.java index 40bb9c5c6..428233457 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/fragment/SearchFragment.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/fragment/SearchFragment.java @@ -30,6 +30,7 @@ import android.view.ViewGroup; import com.hippo.ehviewer.R; import com.hippo.ehviewer.data.ListUrlBuilder; +import com.hippo.ehviewer.ui.ContentActivity; import com.hippo.ehviewer.widget.SearchLayout; import com.hippo.scene.Scene; @@ -38,7 +39,7 @@ public class SearchFragment extends Fragment implements SearchLayout.SearhLayout private static final String VIEW_STATE_TAG = "android:view_state"; - private Activity mActivity; + private ContentActivity mActivity; private View mRootView; private SearchLayout mSearchLayout; @@ -69,13 +70,19 @@ public class SearchFragment extends Fragment implements SearchLayout.SearhLayout public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState) { - mActivity = getActivity(); + mActivity = (ContentActivity) getActivity(); mRootView = inflater.inflate(R.layout.fragment_search, container, false); mSearchLayout = (SearchLayout) mRootView.findViewById(R.id.search_layout); mSearchLayout.setHelper(this); + // Set fit padding bottom + int fixPaddingBottom = mActivity.getFitPaddingBottom(); + if (fixPaddingBottom != -1) { + mSearchLayout.setFitPaddingBottom(mActivity.getFitPaddingBottom()); + } + return mRootView; } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java index 89b3b05f7..bda94d6cd 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java @@ -15,28 +15,8 @@ package com.hippo.ehviewer.ui.scene; -import com.hippo.ehviewer.R; import com.hippo.scene.Scene; public class GalleryDetailScene extends Scene { - @Override - public void onCreate() { - setContentView(R.layout.scene_gallery_detail); - } - - @Override - public void onResume() { - // Empty - } - - @Override - public void onPause() { - dispatchRemove(); - } - - @Override - public void onDestroy() { - dispatchRemove(); - } } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java index 49bc5fa59..5feb07a2f 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java @@ -21,16 +21,21 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; +import android.view.View; import com.hippo.ehviewer.R; import com.hippo.ehviewer.data.ListUrlBuilder; import com.hippo.ehviewer.ui.fragment.GalleryListFragment; import com.hippo.ehviewer.ui.fragment.SearchFragment; import com.hippo.scene.Scene; +import com.hippo.scene.StageActivity; import com.hippo.widget.Appbar; +import org.jetbrains.annotations.NotNull; + public class GalleryListScene extends Scene implements SearchFragment.OnSearchListener { + private StageActivity mActivity; private Resources mResources; private Appbar mAppbar; @@ -39,13 +44,16 @@ public class GalleryListScene extends Scene implements SearchFragment.OnSearchLi private GalleryListPagerAdapter mAdapter; @Override - public void onCreate() { - setContentView(R.layout.scene_gallery_list); + public void onCreate(Bundle savedInstanceState) { + mActivity = getStageActivity(); + mResources = mActivity.getResources(); + } - mResources = getStageActivity().getResources(); - - mAppbar = (Appbar) findViewById(R.id.appbar); - mViewPager = (ViewPager) findViewById(R.id.viewPager); + @Override + public View onCreateSceneView(Bundle savedInstanceState) { + View sceneView = mActivity.getLayoutInflater().inflate(R.layout.scene_gallery_list, null); + mAppbar = (Appbar) sceneView.findViewById(R.id.appbar); + mViewPager = (ViewPager) sceneView.findViewById(R.id.viewPager); mAdapter = new GalleryListPagerAdapter(getSupportFragmentManager()); mViewPager.setAdapter(mAdapter); @@ -54,6 +62,8 @@ public class GalleryListScene extends Scene implements SearchFragment.OnSearchLi SearchFragment.setScene(this); SearchFragment.setOnSearchListener(this); + + return sceneView; } @Override @@ -63,13 +73,10 @@ public class GalleryListScene extends Scene implements SearchFragment.OnSearchLi @Override public void onPause() { - dispatchRemove(); } @Override public void onDestroy() { - dispatchRemove(); - SearchFragment.setScene(null); SearchFragment.setOnSearchListener(null); } @@ -85,7 +92,7 @@ public class GalleryListScene extends Scene implements SearchFragment.OnSearchLi } @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { + protected void onRestoreInstanceState(@NotNull Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); } diff --git a/app/src/main/java/com/hippo/ehviewer/widget/ContentLayout.java b/app/src/main/java/com/hippo/ehviewer/widget/ContentLayout.java new file mode 100644 index 000000000..1640d7614 --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/widget/ContentLayout.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2015 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.ehviewer.widget; + +import android.content.Context; +import android.graphics.Rect; +import android.util.AttributeSet; + +import com.hippo.scene.StageLayout; + +import org.jetbrains.annotations.NotNull; + +public class ContentLayout extends StageLayout { + + private OnGetPaddingListener mOnGetPaddingListener; + + private int mFitPaddingLeft = -1; + private int mFitPaddingTop = -1; + private int mFitPaddingRight = -1; + private int mFitPaddingBottom = -1; + + public ContentLayout(Context context) { + super(context); + } + + public ContentLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ContentLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public ContentLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @SuppressWarnings("deprecation") + @Override + protected boolean fitSystemWindows(@NotNull Rect insets) { + mFitPaddingLeft = insets.left; + mFitPaddingTop = 0; + mFitPaddingRight = insets.right; + mFitPaddingBottom = insets.bottom; + if (mOnGetPaddingListener != null) { + mOnGetPaddingListener.onGetPadding(mFitPaddingLeft, mFitPaddingTop, + mFitPaddingRight, mFitPaddingBottom); + } + + insets.set(0, insets.top, 0, 0); + + return super.fitSystemWindows(insets); + } + + public void setOnGetPaddingListener(OnGetPaddingListener listener) { + mOnGetPaddingListener = listener; + } + + public int getFitPaddingLeft() { + return mFitPaddingLeft; + } + + public int getFitPaddingTop() { + return mFitPaddingTop; + } + + public int getFitPaddingRight() { + return mFitPaddingRight; + } + + public int getFitPaddingBottom() { + return mFitPaddingBottom; + } + + public interface OnGetPaddingListener { + public void onGetPadding(int l, int t, int r, int b); + } +} diff --git a/app/src/main/java/com/hippo/ehviewer/widget/GalleryListView.java b/app/src/main/java/com/hippo/ehviewer/widget/GalleryListView.java new file mode 100644 index 000000000..faacd82b8 --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/widget/GalleryListView.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2015 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.ehviewer.widget; + +public class GalleryListView { +} diff --git a/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java b/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java index 2f4fe04b8..8df6a76ee 100644 --- a/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java +++ b/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java @@ -146,6 +146,15 @@ public class SearchLayout extends FrameLayout implements CompoundButton.OnChecke mFab.setOnClickListener(this); } + public void setFitPaddingBottom(int paddingBottom) { + mSearchContainer.setClipToPadding(false); + mSearchContainer.setPadding( + mSearchContainer.getPaddingLeft(), + mSearchContainer.getPaddingTop(), + mSearchContainer.getPaddingRight(), + paddingBottom); + } + public void setHelper(SearhLayoutHelper helper) { mHelper = helper; } diff --git a/app/src/main/java/com/hippo/scene/Announcer.java b/app/src/main/java/com/hippo/scene/Announcer.java new file mode 100644 index 000000000..5836e9c24 --- /dev/null +++ b/app/src/main/java/com/hippo/scene/Announcer.java @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2015 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.scene; + +import android.os.Bundle; +import android.os.Parcelable; + +import java.io.Serializable; + +public class Announcer { + + private Bundle mExtras; + + public boolean getBooleanExtra(String name, boolean defaultValue) { + return mExtras == null ? defaultValue : + mExtras.getBoolean(name, defaultValue); + } + + public byte getByteExtra(String name, byte defaultValue) { + return mExtras == null ? defaultValue : + mExtras.getByte(name, defaultValue); + } + + public short getShortExtra(String name, short defaultValue) { + return mExtras == null ? defaultValue : + mExtras.getShort(name, defaultValue); + } + + public char getCharExtra(String name, char defaultValue) { + return mExtras == null ? defaultValue : + mExtras.getChar(name, defaultValue); + } + + public int getIntExtra(String name, int defaultValue) { + return mExtras == null ? defaultValue : + mExtras.getInt(name, defaultValue); + } + + public long getLongExtra(String name, long defaultValue) { + return mExtras == null ? defaultValue : + mExtras.getLong(name, defaultValue); + } + + public float getFloatExtra(String name, float defaultValue) { + return mExtras == null ? defaultValue : + mExtras.getFloat(name, defaultValue); + } + + public double getDoubleExtra(String name, double defaultValue) { + return mExtras == null ? defaultValue : + mExtras.getDouble(name, defaultValue); + } + + public String getStringExtra(String name) { + return mExtras == null ? null : mExtras.getString(name); + } + + public CharSequence getCharSequenceExtra(String name) { + return mExtras == null ? null : mExtras.getCharSequence(name); + } + + public T getParcelableExtra(String name) { + return mExtras == null ? null : mExtras.getParcelable(name); + } + + public Parcelable[] getParcelableArrayExtra(String name) { + return mExtras == null ? null : mExtras.getParcelableArray(name); + } + + public Serializable getSerializableExtra(String name) { + return mExtras == null ? null : mExtras.getSerializable(name); + } + + public boolean[] getBooleanArrayExtra(String name) { + return mExtras == null ? null : mExtras.getBooleanArray(name); + } + + public byte[] getByteArrayExtra(String name) { + return mExtras == null ? null : mExtras.getByteArray(name); + } + + public short[] getShortArrayExtra(String name) { + return mExtras == null ? null : mExtras.getShortArray(name); + } + + public char[] getCharArrayExtra(String name) { + return mExtras == null ? null : mExtras.getCharArray(name); + } + + public int[] getIntArrayExtra(String name) { + return mExtras == null ? null : mExtras.getIntArray(name); + } + + public long[] getLongArrayExtra(String name) { + return mExtras == null ? null : mExtras.getLongArray(name); + } + + public float[] getFloatArrayExtra(String name) { + return mExtras == null ? null : mExtras.getFloatArray(name); + } + + public double[] getDoubleArrayExtra(String name) { + return mExtras == null ? null : mExtras.getDoubleArray(name); + } + + public String[] getStringArrayExtra(String name) { + return mExtras == null ? null : mExtras.getStringArray(name); + } + + public CharSequence[] getCharSequenceArrayExtra(String name) { + return mExtras == null ? null : mExtras.getCharSequenceArray(name); + } + + public Bundle getBundleExtra(String name) { + return mExtras == null ? null : mExtras.getBundle(name); + } + + public Bundle getExtras() { + return (mExtras != null) + ? new Bundle(mExtras) + : null; + } + + public Announcer putExtra(String name, boolean value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putBoolean(name, value); + return this; + } + + public Announcer putExtra(String name, byte value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putByte(name, value); + return this; + } + + public Announcer putExtra(String name, char value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putChar(name, value); + return this; + } + + public Announcer putExtra(String name, short value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putShort(name, value); + return this; + } + + public Announcer putExtra(String name, int value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putInt(name, value); + return this; + } + + public Announcer putExtra(String name, long value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putLong(name, value); + return this; + } + + public Announcer putExtra(String name, float value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putFloat(name, value); + return this; + } + + public Announcer putExtra(String name, double value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putDouble(name, value); + return this; + } + + public Announcer putExtra(String name, String value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putString(name, value); + return this; + } + + public Announcer putExtra(String name, CharSequence value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putCharSequence(name, value); + return this; + } + + public Announcer putExtra(String name, Parcelable value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putParcelable(name, value); + return this; + } + + public Announcer putExtra(String name, Parcelable[] value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putParcelableArray(name, value); + return this; + } + + public Announcer putExtra(String name, Serializable value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putSerializable(name, value); + return this; + } + + public Announcer putExtra(String name, boolean[] value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putBooleanArray(name, value); + return this; + } + + public Announcer putExtra(String name, byte[] value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putByteArray(name, value); + return this; + } + + public Announcer putExtra(String name, short[] value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putShortArray(name, value); + return this; + } + + public Announcer putExtra(String name, char[] value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putCharArray(name, value); + return this; + } + + public Announcer putExtra(String name, int[] value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putIntArray(name, value); + return this; + } + + public Announcer putExtra(String name, long[] value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putLongArray(name, value); + return this; + } + + public Announcer putExtra(String name, float[] value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putFloatArray(name, value); + return this; + } + + public Announcer putExtra(String name, double[] value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putDoubleArray(name, value); + return this; + } + + public Announcer putExtra(String name, String[] value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putStringArray(name, value); + return this; + } + + public Announcer putExtra(String name, CharSequence[] value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putCharSequenceArray(name, value); + return this; + } + + public Announcer putExtra(String name, Bundle value) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putBundle(name, value); + return this; + } + + public Announcer putExtras(Announcer src) { + if (src.mExtras != null) { + if (mExtras == null) { + mExtras = new Bundle(src.mExtras); + } else { + mExtras.putAll(src.mExtras); + } + } + return this; + } + + public Announcer putExtras(Bundle extras) { + if (mExtras == null) { + mExtras = new Bundle(); + } + mExtras.putAll(extras); + return this; + } + + public void removeExtra(String name) { + if (mExtras != null) { + mExtras.remove(name); + if (mExtras.size() == 0) { + mExtras = null; + } + } + } +} diff --git a/app/src/main/java/com/hippo/scene/Curtain.java b/app/src/main/java/com/hippo/scene/Curtain.java new file mode 100644 index 000000000..d11999eb9 --- /dev/null +++ b/app/src/main/java/com/hippo/scene/Curtain.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2015 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.scene; + +public class Curtain { +} diff --git a/app/src/main/java/com/hippo/scene/Scene.java b/app/src/main/java/com/hippo/scene/Scene.java index 6b66eefb5..57ba94300 100644 --- a/app/src/main/java/com/hippo/scene/Scene.java +++ b/app/src/main/java/com/hippo/scene/Scene.java @@ -21,9 +21,13 @@ import android.os.Parcelable; import android.support.v4.app.FragmentManager; import android.util.SparseArray; import android.view.View; -import android.widget.FrameLayout; +import android.view.ViewParent; import com.hippo.util.AssertUtils; +import com.hippo.util.Log; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * {@link com.hippo.scene.Scene} is a {@code Activity} of {@link android.app.Activity}. @@ -33,60 +37,43 @@ import com.hippo.util.AssertUtils; */ public abstract class Scene { - private StageActivity mStageActivity; - private FrameLayout mStageView; - private View mRootView; + private @Nullable View mSceneView; - void setStageActivity(StageActivity stageActivity) { - mStageActivity = stageActivity; - mStageView = stageActivity.getStageView(); - } + private static SceneManager sSceneManager; - public void setContentView(int layoutResID) { - mRootView = mStageActivity.getLayoutInflater() - .inflate(layoutResID, mStageView, false); - } - - public void setContentView(View view) { - mRootView = view; - } - - public View findViewById(int id) { - AssertUtils.assertNotNull("Call setContentView before findViewById", - mRootView); - - return mRootView.findViewById(id); - } - - View getRootView() { - return mRootView; + static void setSceneManager(SceneManager sceneManager) { + sSceneManager = sceneManager; } + // If there is no StageActivity for SceneManager, yout will get AssertError public StageActivity getStageActivity() { - return mStageActivity; + StageActivity stageActivity = sSceneManager.getStageActivity(); + AssertUtils.assertNotNull("StageActivity is null", stageActivity); + return stageActivity; } - public void startScene(Class sceneClass) { - mStageActivity.startScene(this, sceneClass); + View getSceneView() { + return mSceneView; + } + + public void startScene(@NotNull Class sceneClass, @Nullable Announcer announcer) { + sSceneManager.startScene(sceneClass, announcer); } public final void finish() { - mStageActivity.finishScene(this); + sSceneManager.finishScene(this); } - void create() { - onCreate(); + void create(Bundle savedInstanceState) { + onCreate(savedInstanceState); + mSceneView = onCreateSceneView(savedInstanceState); - AssertUtils.assertNotNull("You have to call setContentView in onCreate", - mRootView); - - mStageActivity.addSceneView(this); + // Make sure scene view is attach from stage + attachToStage(); } void resume() { onResume(); - - mStageActivity.addSceneView(this); } void pause() { @@ -95,46 +82,118 @@ public abstract class Scene { void destroy() { onDestroy(); + + // Make sure scene view is detached from stage + detachFromeStage(); } /** - * You have to call setContentView in it. + * It is called when scene is created + * + * @param savedInstanceState null for first time, non null for recrearte */ - public abstract void onCreate(); - - public abstract void onResume(); - - public abstract void onPause(); - - public abstract void onDestroy(); + protected void onCreate(Bundle savedInstanceState) { + } /** - * This method should be called to remove when it need to remove + * It is called after {@link #onCreate(android.os.Bundle)}. + * Create view of the scene. + * + * @param savedInstanceState null for first time, non null for recrearte + * @return the view of the scene */ - public final void dispatchRemove() { - mStageActivity.stopSceneRetain(this); + protected @Nullable View onCreateSceneView(Bundle savedInstanceState) { + return null; + } + + protected void onResume() { + } + + protected void onPause() { + } + + protected void onDestroy() { + } + + + /** + * Is scene view attached to stage + * + * @return if scene view is null, always return false; + */ + public boolean isInStage() { + if (mSceneView == null) { + return false; + } else { + ViewParent parent = mSceneView.getParent(); + + if (parent == null) { + return false; + } else if (parent == getStageActivity().getStageLayout()) { + return true; + } else { + throw new IllegalStateException("Scene view should only be the child of stage layout"); + } + } + } + + // Add scene view to stage layout + void attachToStage() { + if (mSceneView != null && !isInStage()) { + + Log.d("doAttachToStage();"); + doAttachToStage(); + } + } + + void attachToStageAsPreScene() { + // TODO + } + + // Remove scene view from stage layout + void detachFromeStage() { + if (mSceneView != null && isInStage()) { + doDetachFromeStage(); + } + } + + void doAttachToStage() { + getStageActivity().attachSceneToStage(this); + } + + void doAttachToStageAsPreScene() { + getStageActivity().attachSceneToStageAsPreScene(this); + } + + void doDetachFromeStage() { + getStageActivity().detachSceneFromStage(this); } public void onBackPressed() { finish(); } - protected void onSaveInstanceState(Bundle outState) { - SparseArray states = new SparseArray<>(); - mRootView.saveHierarchyState(states); - outState.putSparseParcelableArray(Integer.toHexString(hashCode()), states); + // It is constant + private String getStateKey() { + return "scene:" + Integer.toHexString(hashCode()); } - protected void onRestoreInstanceState(Bundle savedInstanceState) { + protected void onSaveInstanceState(Bundle outState) { + SparseArray states = new SparseArray<>(); + mSceneView.saveHierarchyState(states); + outState.putSparseParcelableArray(getStateKey(), states); + } + + protected void onRestoreInstanceState(@NotNull Bundle savedInstanceState) { SparseArray savedStates - = savedInstanceState.getSparseParcelableArray(Integer.toHexString(hashCode())); + = savedInstanceState.getSparseParcelableArray(getStateKey()); if (savedStates != null) { - mRootView.restoreHierarchyState(savedStates); + mSceneView.restoreHierarchyState(savedStates); } } public void startActivityForResult(Intent intent, ActivityResultListener listener) { - mStageActivity.startActivityForResult(intent, listener); + getStageActivity().startActivityForResult(intent, listener); } /** @@ -142,7 +201,7 @@ public abstract class Scene { * with StageActivity. */ public FragmentManager getSupportFragmentManager() { - return mStageActivity.getSupportFragmentManager(); + return getStageActivity().getSupportFragmentManager(); } public interface ActivityResultListener { diff --git a/app/src/main/java/com/hippo/scene/SceneApplication.java b/app/src/main/java/com/hippo/scene/SceneApplication.java new file mode 100644 index 000000000..3c2880b57 --- /dev/null +++ b/app/src/main/java/com/hippo/scene/SceneApplication.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2015 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.scene; + +import android.app.Application; + +public class SceneApplication extends Application { + + private SceneManager mSceneManager; + + @Override + public void onCreate() { + mSceneManager = new SceneManager(); + StageActivity.setSceneManager(mSceneManager); + Scene.setSceneManager(mSceneManager); + } + + public SceneManager getSceneManager() { + return mSceneManager; + } +} diff --git a/app/src/main/java/com/hippo/scene/SceneManager.java b/app/src/main/java/com/hippo/scene/SceneManager.java new file mode 100644 index 000000000..75d7d294d --- /dev/null +++ b/app/src/main/java/com/hippo/scene/SceneManager.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2015 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.scene; + +import android.os.Bundle; + +import com.hippo.util.Log; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Stack; + +class SceneManager { + + private static final String TAG = SceneManager.class.getSimpleName(); + + private Stack mSceneStack = new Stack<>(); + private StageActivity mStageActivity; + + // Should only be called by SceneApplication + SceneManager() { + } + + void setStageActivity(StageActivity stageActivity) { + mStageActivity = stageActivity; + } + + StageActivity getStageActivity() { + return mStageActivity; + } + + void startScene(@NotNull Class sceneClass, @Nullable Announcer announcer) { + Scene scene; + try { + scene = (Scene) sceneClass.newInstance(); + } catch (InstantiationException e) { + throw new IllegalStateException("Can't instance " + sceneClass.getName()); + } catch (IllegalAccessException e) { + throw new IllegalStateException("The constructor of " + + sceneClass.getName() + " is not visible"); + } catch (ClassCastException e) { + throw new IllegalStateException(sceneClass.getName() + " can not cast to scene"); + } + + Scene topScene = getTopState(); + if (topScene != null) { + topScene.pause(); + } + + mSceneStack.push(scene); + + scene.create(null); + scene.resume(); + } + + void finishScene(@NotNull Scene scene) { + if (mSceneStack.remove(scene)) { + scene.destroy(); + } else { + Log.e(TAG, "The scene is not in stage"); + } + } + + boolean onBackPressed() { + Scene scene = getTopState(); + if (scene != null) { + scene.onBackPressed(); + return true; + } else { + Log.w(TAG, "There is no scene in the stage"); + return false; + } + } + + private Scene getTopState() { + if (!mSceneStack.isEmpty()) { + return mSceneStack.peek(); + } else { + return null; + } + } + + private Scene getSecondTopState() { + int secondTopIndex = mSceneStack.size() - 2; + if (secondTopIndex >= 0) { + return mSceneStack.get(secondTopIndex); + } else { + return null; + } + } + + protected void onSaveInstanceState(Bundle outState) { + for (Scene scene : mSceneStack) { + scene.onSaveInstanceState(outState); + } + } + + protected void onRestoreInstanceState(@NotNull Bundle savedInstanceState) { + for (Scene scene : mSceneStack) { + // Recreate + scene.create(savedInstanceState); + scene.resume(); + scene.onRestoreInstanceState(savedInstanceState); + } + } +} diff --git a/app/src/main/java/com/hippo/scene/StageActivity.java b/app/src/main/java/com/hippo/scene/StageActivity.java index 7de4f2801..b2a16430e 100644 --- a/app/src/main/java/com/hippo/scene/StageActivity.java +++ b/app/src/main/java/com/hippo/scene/StageActivity.java @@ -22,138 +22,60 @@ import android.util.SparseArray; import com.hippo.ehviewer.ui.AbsActionBarActivity; import com.hippo.util.IntIdGenerator; -import java.util.LinkedList; -import java.util.Stack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public abstract class StageActivity extends AbsActionBarActivity { - private Stack mSceneStack = new Stack<>(); - private LinkedList mScenseActionQueue = new LinkedList<>(); - private Scene mCurrentScene = null; - private Scene mRetainedScene = null; - private IntIdGenerator mActivityResultIdGenerator = IntIdGenerator.create(); private SparseArray mActivityResultListenerMap = new SparseArray<>(); - public abstract StageLayout getStageView(); + private static SceneManager sSceneManager; - private void pushScene(Class sceneClass) { - Scene scene = null; - try { - scene = (Scene) sceneClass.newInstance(); - } catch (InstantiationException e) { - throw new IllegalStateException("Can't instance " + sceneClass.getName()); - } catch (IllegalAccessException e) { - throw new IllegalStateException("The constructor of " + - sceneClass.getName() + " is not vivible"); - } catch (ClassCastException e) { - throw new IllegalStateException(sceneClass.getName() + " can not cast to scene"); - } - - scene.setStageActivity(this); - - Scene lastScene = mCurrentScene; - mCurrentScene = scene; - mCurrentScene.create(); - if (lastScene != null) { - // It is not the first scense - mSceneStack.push(lastScene); - - mRetainedScene = lastScene; - lastScene.pause(); - } + static void setSceneManager(SceneManager sceneManager) { + sSceneManager = sceneManager; } - private void popScense() { - if (mSceneStack.isEmpty()) { - // It is the last scene - mRetainedScene = mCurrentScene; - mCurrentScene.destroy(); - } else { - Scene previousScene = mCurrentScene; - mCurrentScene = mSceneStack.pop(); - mRetainedScene = previousScene; + public abstract StageLayout getStageLayout(); - mCurrentScene.resume(); - previousScene.destroy(); - } + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ((SceneApplication) getApplication()).getSceneManager().setStageActivity(this); } - void addSceneView(Scene scene) { - if (scene != mCurrentScene) { - throw new IllegalStateException("This scene should be current scene."); - } + @Override + protected void onDestroy() { + super.onDestroy(); - getStageView().addView(scene.getRootView()); + ((SceneApplication) getApplication()).getSceneManager().setStageActivity(null); } - void stopSceneRetain(Scene scene) { - if (mRetainedScene == null) { - throw new IllegalStateException("Do not call dispatchRemove more than " + - "once."); - } - if (mRetainedScene != scene) { - throw new IllegalStateException("Only call dispatchRemove in onPause " + - "and onDestroy"); - } - - Scene retainScene = mRetainedScene; - mRetainedScene = null; - getStageView().removeView(scene.getRootView()); - - if (retainScene == mCurrentScene) { - // No need to handle scene action - mScenseActionQueue.clear(); - // It is the last scene, let's finish the activity. - finish(); - } else { - // Handle SceneAction - if (!mScenseActionQueue.isEmpty()) { - mScenseActionQueue.poll().doAction(); - } - } + void attachSceneToStage(Scene scene) { + getStageLayout().addView(scene.getSceneView()); } - protected void startFirstScene(Class sceneClass) { - if (mCurrentScene != null) { - throw new IllegalStateException("Only call startFirstScene to start " + - "first scene."); - } - - pushScene(sceneClass); + void attachSceneToStageAsPreScene(Scene scene) { + StageLayout stageLayout = getStageLayout(); + stageLayout.addView(scene.getSceneView(), stageLayout.getChildCount() - 1); } - void startScene(Scene fromScene, Class sceneClass) { - if (mRetainedScene == null) { - // No retained scene, no animation - if (fromScene == mCurrentScene) { - // Only current scene can start new scene. - // If not, just miss it. - pushScene(sceneClass); - } - } else { - mScenseActionQueue.offer(new StartSceneAction(fromScene, sceneClass)); - } + void detachSceneFromStage(Scene scene) { + getStageLayout().removeView(scene.getSceneView()); } - void finishScene(Scene scene) { - if (scene != mRetainedScene && scene != mCurrentScene) { - if (mSceneStack.contains(scene)) { - // Remove without animation - getStageView().removeView(scene.getRootView()); - mSceneStack.remove(scene); - } - } else { - if (mRetainedScene == null) { - // Because scene can't be null, so scene == mCurrentScene - popScense(); - } else { - mScenseActionQueue.offer(new FinishSceneAction(scene)); - } - } + public void startScene(@NotNull Class sceneClass, @Nullable Announcer announcer) { + sSceneManager.startScene(sceneClass, announcer); } + /** + * Start new Activity for result to listener + * + * @param intent the intent for new Activity + * @param listener callback + */ public void startActivityForResult(Intent intent, Scene.ActivityResultListener listener) { int id = mActivityResultIdGenerator.nextId(); mActivityResultListenerMap.put(id, listener); @@ -173,8 +95,8 @@ public abstract class StageActivity extends AbsActionBarActivity { @Override public void onBackPressed() { - if (mCurrentScene != null) { - mCurrentScene.onBackPressed(); + if (!sSceneManager.onBackPressed()) { + super.onBackPressed(); } } @@ -182,56 +104,13 @@ public abstract class StageActivity extends AbsActionBarActivity { protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - for (Scene scene : mSceneStack) { - scene.onSaveInstanceState(outState); - } - if (mCurrentScene != null) { - mCurrentScene.onSaveInstanceState(outState); - } + sSceneManager.onSaveInstanceState(outState); } @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { + protected void onRestoreInstanceState(@NotNull Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); - for (Scene scene : mSceneStack) { - scene.onRestoreInstanceState(savedInstanceState); - } - if (mCurrentScene != null) { - mCurrentScene.onRestoreInstanceState(savedInstanceState); - } + sSceneManager.onRestoreInstanceState(savedInstanceState); } - - interface SceneAction { - public void doAction(); - } - - class StartSceneAction implements SceneAction { - private Scene mFromScene; - private Class mSceneClass; - - public StartSceneAction(Scene fromScene, Class sceneClass) { - mFromScene = fromScene; - mSceneClass = sceneClass; - } - - @Override - public void doAction() { - startScene(mFromScene, mSceneClass); - } - } - - class FinishSceneAction implements SceneAction { - private Scene mScene; - - public FinishSceneAction(Scene scene) { - mScene = scene; - } - - @Override - public void doAction() { - finishScene(mScene); - } - } - } diff --git a/app/src/main/java/com/hippo/scene/StageLayout.java b/app/src/main/java/com/hippo/scene/StageLayout.java index 9831768e3..34f9de466 100644 --- a/app/src/main/java/com/hippo/scene/StageLayout.java +++ b/app/src/main/java/com/hippo/scene/StageLayout.java @@ -23,6 +23,8 @@ import android.util.AttributeSet; import android.util.SparseArray; import android.widget.FrameLayout; +import org.jetbrains.annotations.NotNull; + public class StageLayout extends FrameLayout { public StageLayout(Context context) { @@ -43,12 +45,12 @@ public class StageLayout extends FrameLayout { } @Override - protected void dispatchSaveInstanceState(SparseArray container) { + protected void dispatchSaveInstanceState(@NotNull SparseArray container) { // Do nothing } @Override - protected void dispatchRestoreInstanceState(SparseArray container) { + protected void dispatchRestoreInstanceState(@NotNull SparseArray container) { // Do nothing } } diff --git a/app/src/main/java/com/hippo/util/NotEqualsException.java b/app/src/main/java/com/hippo/util/AssertError.java similarity index 84% rename from app/src/main/java/com/hippo/util/NotEqualsException.java rename to app/src/main/java/com/hippo/util/AssertError.java index fc7852a75..2646ceca9 100644 --- a/app/src/main/java/com/hippo/util/NotEqualsException.java +++ b/app/src/main/java/com/hippo/util/AssertError.java @@ -15,9 +15,9 @@ package com.hippo.util; -public class NotEqualsException extends Exception { +public class AssertError extends Error { - public NotEqualsException(String detailMessage) { + public AssertError(String detailMessage) { super(detailMessage); } } diff --git a/app/src/main/java/com/hippo/util/AssertException.java b/app/src/main/java/com/hippo/util/AssertException.java new file mode 100644 index 000000000..66abbb70a --- /dev/null +++ b/app/src/main/java/com/hippo/util/AssertException.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2015 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.util; + +public class AssertException extends Exception { + + public AssertException(String detailMessage) { + super(detailMessage); + } +} diff --git a/app/src/main/java/com/hippo/util/AssertUtils.java b/app/src/main/java/com/hippo/util/AssertUtils.java index 59db485c5..55518e762 100644 --- a/app/src/main/java/com/hippo/util/AssertUtils.java +++ b/app/src/main/java/com/hippo/util/AssertUtils.java @@ -17,22 +17,29 @@ package com.hippo.util; public class AssertUtils { - public static void assertNotNull(Object object) throws NullPointerException { - assertNotNull(null, object); - } - - public static void assertNotNull(String message, Object object) - throws NullPointerException { + public static void assertNotNull(String message, Object object) { if (object == null) { - throw new NullPointerException(message); + throw new AssertError(message); } } - public static void assertEquals(String message, int expected, int actual) - throws NotEqualsException { + public static void assertEquals(String message, int expected, int actual) { if (expected != actual) { - throw new NotEqualsException(message); + throw new AssertError(message); } } + public static void assertNotNullEx(String message, Object object) + throws AssertException { + if (object == null) { + throw new AssertException(message); + } + } + + public static void assertEqualsEx(String message, int expected, int actual) + throws AssertException { + if (expected != actual) { + throw new AssertException(message); + } + } } diff --git a/app/src/main/java/com/hippo/widget/DrawerFrameLayout.java b/app/src/main/java/com/hippo/widget/DrawerFrameLayout.java index 19e25e83d..25ae55563 100644 --- a/app/src/main/java/com/hippo/widget/DrawerFrameLayout.java +++ b/app/src/main/java/com/hippo/widget/DrawerFrameLayout.java @@ -33,6 +33,11 @@ public class DrawerFrameLayout extends FrameLayout { private OnGetPaddingListener mOnGetPaddingListener; + private int mFitPaddingLeft = -1; + private int mFitPaddingTop = -1; + private int mFitPaddingRight = -1; + private int mFitPaddingBottom = -1; + public DrawerFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0, 0); @@ -72,9 +77,13 @@ public class DrawerFrameLayout extends FrameLayout { @SuppressWarnings("deprecation") @Override protected boolean fitSystemWindows(@NotNull Rect insets) { + mFitPaddingLeft = insets.left; + mFitPaddingTop = insets.top; + mFitPaddingRight = insets.right; + mFitPaddingBottom = insets.bottom; if (mOnGetPaddingListener != null) { - mOnGetPaddingListener.onGetPadding(insets.left, insets.top, - insets.right, insets.bottom); + mOnGetPaddingListener.onGetPadding(mFitPaddingLeft, mFitPaddingTop, + mFitPaddingRight, mFitPaddingBottom); } insets.set(0, 0, 0, 0); @@ -86,6 +95,22 @@ public class DrawerFrameLayout extends FrameLayout { mOnGetPaddingListener = listener; } + public int getFitPaddingLeft() { + return mFitPaddingLeft; + } + + public int getFitPaddingTop() { + return mFitPaddingTop; + } + + public int getFitPaddingRight() { + return mFitPaddingRight; + } + + public int getFitPaddingBottom() { + return mFitPaddingBottom; + } + public interface OnGetPaddingListener { public void onGetPadding(int l, int t, int r, int b); } diff --git a/app/src/main/res/layout/activity_content.xml b/app/src/main/res/layout/activity_content.xml index d80fc0c65..a1b92c363 100644 --- a/app/src/main/res/layout/activity_content.xml +++ b/app/src/main/res/layout/activity_content.xml @@ -20,10 +20,11 @@ android:layout_height="match_parent" android:fitsSystemWindows="true"> - + android:layout_height="match_parent" + android:fitsSystemWindows="true"/>