恢复时滚动视图变黑 activity
Scrollview goes black when resuming activity
当我使用 ScrollView 离开 activity 然后 return 导航到它时,ScrollView 变黑。发射时,颜色是正确的。就在我离开并返回时,它变黑了。我尝试设置 ScrollView 和内部 LinearLayouts 的背景,但没有任何区别。 ScrollView 由 ViewPager 中的片段膨胀,以防产生差异。
知道为什么会这样吗?
这是XML
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scroll_formatted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false">
<LinearLayout style="@style/LinearLayoutVertical">
<ImageView
android:id="@+id/image_formatted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="@string/image_review_cd"
android:scaleType="centerCrop"/>
<LinearLayout
style="@style/LinearLayoutVertical.WrappedVertical"
android:id="@+id/subject_rating_formatted">
<TextView
android:id="@+id/subject_formatted"
style="@style/TextView.Subject.Bold"
android:background="?darkBackground"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?darkBackground">
<RatingBar
android:id="@+id/rating_formatted"
style="@style/RatingBarFiveStar.Indicator.PointOneStep"
android:background="?darkBackground"/>
</FrameLayout>
<TextView
android:id="@+id/stamp_formatted"
style="@style/FormattedText.Stamp"
android:background="?darkBackground"/>
</LinearLayout>
<TextView
android:id="@+id/headline_formatted"
style="@style/TextView.Headline"/>
<TextView
android:id="@+id/tags_formatted"
style="@style/FormattedTitleValue"/>
<include
android:id="@+id/comment_formatted"
layout="@layout/formatted_title_value"/>
<include
android:id="@+id/locations_formatted"
layout="@layout/formatted_title_value"/>
<include
android:id="@+id/criteria_formatted"
layout="@layout/formatted_title_value"/>
<include
android:id="@+id/facts_formatted"
layout="@layout/formatted_title_value"/>
<include
android:id="@+id/images_formatted"
layout="@layout/formatted_title_data"/>
</LinearLayout>
</ScrollView>
编辑:这里是 activity 和片段:
Activity
public class ActivityFormatReview extends FragmentActivity implements LaunchableUi,
OptionSelectListener, FormattedPagerAdapter.FragmentsObserver {
private static final String TAG = TagKeyGenerator.getTag(ActivityFormatReview.class);
private static final String RETAIN_VIEW
= TagKeyGenerator.getKey(ActivityFormatReview.class, "RetainView");
private static final int LAYOUT = R.layout.view_pager;
private static final int PAGER = R.id.pager;
private FormattedPagerAdapter mAdapter;
private ViewPager mPager;
private FragmentInitialiser mInitialiser;
public ReviewNode getNode(ReviewId id) {
return mAdapter.getNode(id);
}
public void remove(FragmentFormatReview fragment) {
mAdapter.removeFragment(fragment);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(LAYOUT);
Bundle args = getIntent().getBundleExtra(getLaunchTag());
if (args == null) throwNoReview();
AppInstanceAndroid app = AppInstanceAndroid.getInstance(this);
ReviewNode node = app.unpackNode(args);
if (node == null) throwNoReview();
boolean isPublished = NodeLauncher.isPublished(args);
mPager = findViewById(PAGER);
mAdapter = new FormattedPagerAdapter(node, new NodeComparatorMostRecent(),
getSupportFragmentManager(), this, isPublished);
mPager.setAdapter(mAdapter);
mInitialiser = new FragmentInitialiser(app.getUi());
mPager.addOnLayoutChangeListener(mInitialiser);
mPager.addOnPageChangeListener(mInitialiser);
}
@Override
public void onNoFragmentsLeft() {
finish();
}
@Override
public void updateTitle(String title) {
mInitialiser.setTitle(title);
}
@Override
protected void onDestroy() {
super.onDestroy();
mAdapter.detach();
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(RETAIN_VIEW, true);
super.onSaveInstanceState(outState);
}
@Override
public String getLaunchTag() {
return TAG;
}
@Override
public void launch(UiTypeLauncher launcher) {
launcher.launch(getClass(), getLaunchTag());
}
@Override
public boolean onOptionSelected(int requestCode, String option) {
FragmentFormatReview fragment = getVisibleFragment();
return fragment != null && fragment.onOptionSelected(requestCode, option);
}
@Override
public boolean onOptionsCancelled(int requestCode) {
FragmentFormatReview fragment = getVisibleFragment();
return fragment != null && fragment.onOptionsCancelled(requestCode);
}
@Override
protected void onResume() {
super.onResume();
AppInstanceAndroid.setActivity(this);
}
@Nullable
private FragmentFormatReview getVisibleFragment() {
return mAdapter.getFragment(mPager.getCurrentItem());
}
private void throwNoReview() {
throw new RuntimeException("No review found");
}
private class FragmentInitialiser implements ViewPager.OnLayoutChangeListener, ViewPager
.OnPageChangeListener {
private UiSuite mUi;
private FragmentInitialiser(UiSuite ui) {
mUi = ui;
}
@Override
public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int
i6, int i7) {
setTitle();
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
setTitle();
}
@Override
public void onPageScrollStateChanged(int state) {
}
private void setTitle() {
FragmentFormatReview fragment = getVisibleFragment();
if (fragment != null) {
setTitle(fragment.isPublished() ?
mAdapter.getTitle(fragment) : Strings.Screens.PREVIEW);
}
}
private void setTitle(String title) {
mUi.getCurrentScreen().setTitle(title);
}
}
}
片段
public class FragmentFormatReview extends PagerAdapterBasic.PageableFragment implements
ReviewNode.NodeObserver,
DataReference.InvalidationListener,
OptionSelectListener {
private static final String ID = TagKeyGenerator.getKey(FragmentFormatReview.class,
"ReviewId");
private static final String PUBLISHED = TagKeyGenerator.getKey(FragmentFormatReview.class,
"published");
private static final int LAYOUT = R.layout.fragment_review_formatted;
private static final int IMAGE = R.id.image_formatted;
private static final int SUBJECT = R.id.subject_formatted;
private static final int RATING = R.id.rating_formatted;
private static final int HEADLINE = R.id.headline_formatted;
private static final int STAMP = R.id.stamp_formatted;
private static final int COMMENT = R.id.comment_formatted;
private static final int TAGS = R.id.tags_formatted;
private static final int CRITERIA = R.id.criteria_formatted;
private static final int FACTS = R.id.facts_formatted;
private static final int LOCATIONS = R.id.locations_formatted;
private static final int IMAGES = R.id.images_formatted;
private static final int DATA = R.id.section_data;
private static final int IMAGE_PADDING = R.dimen.formatted_image_padding;
private static final int IMAGE_PLACEHOLDER = R.drawable.image_placeholder;
private static final ReviewViewParams.CellDimension FULL
= ReviewViewParams.CellDimension.FULL;
private static final ReviewViewParams.CellDimension HALF
= ReviewViewParams.CellDimension.HALF;
private boolean mIsPublished = true;
private ReviewNode mNode;
private UiSuite mUi;
private RepositorySuite mRepo;
private MenuUi mMenu;
private CoverNodeBannerUi mCover;
private ViewUi<TextView, String> mSubject;
private ViewUi<RatingBar, Float> mRating;
private ViewUi<TextView, RefDataList<DataTag>> mTags;
private ViewUi<TextView, AuthorReference> mStamp;
private FormattedSectionUi<RefCommentList> mComment;
private FormattedSectionUi<RefDataList<DataCriterion>> mCriteria;
private FormattedSectionUi<RefDataList<DataFact>> mFacts;
private FormattedSectionUi<RefDataList<DataLocation>> mLocations;
private FormattedSectionUi<ReviewItemReference<DataSize>> mImages;
public static FragmentFormatReview newInstance(String nodeId, boolean isPublished) {
//Can't use FactoryFragment as Support fragment rather than normal fragment
Bundle args = new Bundle();
args.putString(ID, nodeId);
args.putBoolean(PUBLISHED, isPublished);
FragmentFormatReview fragment = new FragmentFormatReview();
fragment.setArguments(args);
return fragment;
}
public boolean isPublished() {
return mIsPublished;
}
@Override
public String getPageId() {
return mNode.getReviewId().toString();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
setHasOptionsMenu(true);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
AppInstanceAndroid app = AppInstanceAndroid.getInstance(getContext());
mUi = app.getUi();
mRepo = app.getRepository();
View v = inflater.inflate(LAYOUT, container, false);
Bundle args = getArguments();
if (args == null) {
noReview();
return v;
}
mIsPublished = args.getBoolean(PUBLISHED);
setNode(args);
setMenu();
setCover(v);
setSubject(v);
setRating(v);
setStamp(v);
setComment(v);
setTags(v);
setCriteria(v);
setFacts(v);
setLocations(v);
setImages(v);
return v;
}
@Override
public void onCreateOptionsMenu(Menu menu, android.view.MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
mMenu.inflate(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(android.view.MenuItem item) {
return mMenu.onItemSelected(item) || super.onOptionsItemSelected(item);
}
@Override
public void onChildAdded(ReviewNode child) {
update();
}
@Override
public void onChildRemoved(ReviewNode child) {
update();
}
@Override
public void onNodeChanged() {
update();
}
@Override
public void onTreeChanged() {
update();
}
@Override
public boolean onOptionSelected(int requestCode, String option) {
return mMenu.onOptionSelected(requestCode, option);
}
@Override
public boolean onOptionsCancelled(int requestCode) {
return mMenu.onOptionsCancelled(requestCode);
}
@Override
public void onResume() {
super.onResume();
update();
}
@Override
public void onDestroyView() {
super.onDestroyView();
mNode.unregisterObserver(this);
}
@Override
public void onReferenceInvalidated(DataReference<?> reference) {
if (getContainer() != null) getContainer().remove(this);
}
private FactoryCommands getCommandsFactory() {
return mUi.getCommandsFactory();
}
private ConverterGv getConverter() {
return mUi.getGvConverter();
}
private ActivityFormatReview getContainer() {
try {
return (ActivityFormatReview) getActivity();
} catch (ClassCastException e) {
throw new RuntimeException(e);
}
}
private void noReview() {
AppInstanceAndroid app = AppInstanceAndroid.getInstance(getContext());
CurrentScreen currentScreen = app.getUi().getCurrentScreen();
currentScreen.showToast(Strings.Toasts.REVIEW_NOT_FOUND);
currentScreen.close();
}
private void setNode(Bundle args) {
String reviewId = args.getString(ID);
if (reviewId == null) {
noReview();
return;
}
mNode = getContainer().getNode(new DatumReviewId(reviewId));
mNode.registerObserver(this);
ReviewReference reference = mNode.getReference();
if (mNode.isLeaf() && reference != null) reference.registerListener(this);
}
private void setMenu() {
AppInstanceAndroid app = AppInstanceAndroid.getInstance(getContext());
UiSuite ui = app.getUi();
MenuActionItem<GvData> upAction = new MaiUpAppLevel<>(app);
MenuAction<?> action;
if (mIsPublished) {
OptionsCommand command
= getCommandsFactory().newReviewOptionsSelector(ReviewOptionsSelector
.SelectorType.ALL, new NodeAuthorId(mNode));
MaiOptionsCommand<GvData> mai = new MaiOptionsCommand<>(command);
action = new MenuOptionsAppLevel(Strings.Menu.REVIEWS, upAction, mai, ui);
} else {
action = new MenuUpAppLevel(Strings.Screens.PREVIEW, upAction, ui);
}
mMenu = new MenuUi(action);
}
private void update() {
mCover.update();
mImages.update();
mSubject.update();
mRating.update();
mStamp.update();
mTags.update();
mComment.update();
mLocations.update();
mCriteria.update();
mFacts.update();
}
@Nullable
private Command launchView(GvDataType<?> type) {
return mIsPublished ? newLaunchViewCommand(type) : null;
}
private void setCover(View v) {
CellDimensionsCalculator calculator = new CellDimensionsCalculator(getActivity());
CellDimensionsCalculator.Dimensions dims = calculator.calcDimensions(FULL, FULL, 0);
Bitmap placeholder = BitmapFactory.decodeResource(getResources(), IMAGE_PLACEHOLDER);
mCover = new CoverNodeBannerUi((ImageView) v.findViewById(IMAGE), mNode,
mRepo.getAuthorsRepo().getProfile(mNode.getAuthorId()).getProfileImage(),
placeholder, dims);
setLaunchOnClick(mCover, getCommandsFactory().newLaunchBespokeViewCommand(mNode,
"Images", GvImage.TYPE));
}
private void setSubject(View v) {
mSubject = new SubjectNodeUi((TextView) v.findViewById(SUBJECT), mNode, null);
}
private void setRating(View v) {
mRating = new RatingBarTouchable((RatingBar) v.findViewById(RATING), mNode, null);
}
private void setStamp(View v) {
mStamp = new StampNodeUi((TextView) v.findViewById(STAMP), mNode, mRepo.getAuthorsRepo());
setLaunchOnClick(mStamp, launchAuthor());
}
private void setTags(View v) {
mTags = new TagsNodeUi((TextView) v.findViewById(TAGS), mNode);
setLaunchOnClick(mTags, GvTag.TYPE);
}
private void setComment(View v) {
mComment = new CommentNodeUi(getSection(v, COMMENT), (TextView) v.findViewById(HEADLINE),
mNode, launchView(GvComment.TYPE));
}
private void setLocations(View v) {
mLocations = newDataUi(v, LOCATIONS, Strings.Formatted.LOCATIONS, GvLocation.TYPE,
getConverter().newConverterLocations(), VhLocationFormatted.class,
new SimpleViewUi.ReferenceValueGetter<RefDataList<DataLocation>>() {
@Override
public RefDataList<DataLocation> getValue() {
return mNode.getLocations();
}
});
}
private void setCriteria(View v) {
mCriteria = newDataUi(v, CRITERIA, Strings.Formatted.CRITERIA, GvCriterion.TYPE,
getConverter().newConverterCriteria(), VhCriterionFormatted.class,
new SimpleViewUi.ReferenceValueGetter<RefDataList<DataCriterion>>() {
@Override
public RefDataList<DataCriterion> getValue() {
return mNode.getCriteria();
}
});
}
private void setFacts(View v) {
mFacts = newDataUi(v, FACTS, Strings.Formatted.FACTS, GvFact.TYPE,
getConverter().newConverterFacts(), VhFactFormatted.class,
new SimpleViewUi.ReferenceValueGetter<RefDataList<DataFact>>() {
@Override
public RefDataList<DataFact> getValue() {
return mNode.getFacts();
}
});
}
private void setImages(View v) {
LinearLayout section = getSection(v, IMAGES);
RecyclerView grid = section.findViewById(DATA);
float padding = getResources().getDimensionPixelSize(IMAGE_PADDING);
CellDimensionsCalculator calculator = new CellDimensionsCalculator(getActivity());
CellDimensionsCalculator.Dimensions dims = calculator.calcDimensions(HALF, HALF, (int)
padding);
ViewUi<RecyclerView, RefDataList<DataImage>> dataView = newGridUi
(grid, VhImage.class, 1, (int) padding, dims, getConverter().newConverterImages(),
new SimpleViewUi.ReferenceValueGetter<RefDataList<DataImage>>() {
@Override
public RefDataList<DataImage> getValue() {
return mNode.getImages();
}
});
mImages = new ImagesNodeUi(section, dataView, mNode);
}
private void setLaunchOnClick(ViewUi<?, ?> layout, GvDataType<?> type) {
Command onClick = launchView(type);
setLaunchOnClick(layout, onClick);
}
private void setLaunchOnClick(ViewUi<?, ?> layout, @Nullable Command onClick) {
if (mIsPublished && onClick != null) layout.setOnClickCommand(onClick);
}
private <T1 extends HasReviewId, T2 extends GvData, Vh extends ViewHolder>
ViewUi<RecyclerView, RefDataList<T1>>
newGridUi(RecyclerView view, Class<Vh> vhClass,
int span, int padding, CellDimensionsCalculator.Dimensions dims,
DataConverter<T1, T2, ? extends GvDataList<T2>> converter,
SimpleViewUi.ReferenceValueGetter<RefDataList<T1>> getter) {
IdableDataList<T1> empty = new IdableDataList<>(getter.getValue().getReviewId());
GvDataType<T2> dataType = converter.convert(empty).getGvDataType();
GvDataRefAdapter<T1, T2, Vh> adapter
= new GvDataRefAdapter<>(getter, converter, new VhFactory<>(vhClass), dims);
Command onClick = mIsPublished ? newLaunchViewCommand(dataType) : null;
view.addItemDecoration(new PaddedItemDecoration(padding));
return new HorizontalGridUi<>(getContext(), view, adapter, span, onClick);
}
private Command newLaunchViewCommand(GvDataType<?> dataType) {
return getCommandsFactory().newLaunchViewCommand(mUi.newDataView(mNode, dataType));
}
private Command launchAuthor() {
return mUi.getCommandsFactory().newLaunchAuthorCommand(mNode.getAuthorId());
}
private <T extends HasReviewId, G extends GvData> DataExpandableUi<T>
newDataUi(View v, int sectionId, String title, GvDataType<G> dataType,
DataConverter<T, G, ?> converter, Class<? extends ViewHolder> vhClass,
SimpleViewUi.ReferenceValueGetter<RefDataList<T>> getter) {
DataExpandableUi<T> ui = new DataExpandableUi<>(getContext(), getSection
(v, sectionId), title, getter, newVhFactory(vhClass), converter);
setLaunchOnClick(ui, dataType);
return ui;
}
@NonNull
private ViewHolderFactory<ViewHolder> newVhFactory(final Class<? extends ViewHolder> vhClass) {
return new ViewHolderFactory<ViewHolder>() {
@Override
public ViewHolder newViewHolder() {
try {
return vhClass.newInstance();
} catch (java.lang.InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
};
}
private LinearLayout getSection(View v, int id) {
return (LinearLayout) v.findViewById(id);
}
private static class NodeAuthorId extends DatumAuthorId {
private ReviewNode mNode;
private NodeAuthorId(ReviewNode node) {
super(node.getReviewId(), node.getAuthorId().toString());
mNode = node;
}
@Override
public ReviewId getReviewId() {
return mNode.getReviewId();
}
@Override
public String toString() {
return mNode.getAuthorId().toString();
}
}
private static class PaddedItemDecoration extends RecyclerView.ItemDecoration {
private final int mPadding;
PaddedItemDecoration(int padding) {
mPadding = padding;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
outRect.right = mPadding;
}
}
}
编辑 2:这是清单条目:
<activity
android:name=".ApplicationPlugins.PlugIns.UiPlugin.UiAndroid.Implementation.Act
ivities.ActivityFormatReview"
android:configChanges="orientation"
android:exported="true"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan" >
</activity>
在您的滚动视图上设置背景
在XML:
android:background="@color/Your_White_Color"
变成这样
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scroll_formatted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:background="@color/Your_White_Color">
或在代码中:
ScrollView scrollView = (ScrollView) findViewById(R.id.scroll_formatted);
scrollView.setBackground(R.color.Your_White_Color);
应该是不错的打印屏幕,从视图上更好理解
受到 Patrick R. 评论的启发,我尝试将背景设置为纯色的可绘制对象。在发布我的问题之前,我曾尝试直接设置颜色,但没有成功。也没有将滚动视图包装在框架布局中。但是,将背景设置为纯色的可绘制对象似乎可以解决问题
滚动视图:
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scroll_formatted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:background="@drawable/background">
background.xml
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?dominantBackground" />
</shape>
我完全不知道为什么会这样,所以不能肯定地说它是否在所有情况下都解决了问题,但它确实解决了我能够重复产生问题的情况。
当我使用 ScrollView 离开 activity 然后 return 导航到它时,ScrollView 变黑。发射时,颜色是正确的。就在我离开并返回时,它变黑了。我尝试设置 ScrollView 和内部 LinearLayouts 的背景,但没有任何区别。 ScrollView 由 ViewPager 中的片段膨胀,以防产生差异。
知道为什么会这样吗?
这是XML
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scroll_formatted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false">
<LinearLayout style="@style/LinearLayoutVertical">
<ImageView
android:id="@+id/image_formatted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="@string/image_review_cd"
android:scaleType="centerCrop"/>
<LinearLayout
style="@style/LinearLayoutVertical.WrappedVertical"
android:id="@+id/subject_rating_formatted">
<TextView
android:id="@+id/subject_formatted"
style="@style/TextView.Subject.Bold"
android:background="?darkBackground"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?darkBackground">
<RatingBar
android:id="@+id/rating_formatted"
style="@style/RatingBarFiveStar.Indicator.PointOneStep"
android:background="?darkBackground"/>
</FrameLayout>
<TextView
android:id="@+id/stamp_formatted"
style="@style/FormattedText.Stamp"
android:background="?darkBackground"/>
</LinearLayout>
<TextView
android:id="@+id/headline_formatted"
style="@style/TextView.Headline"/>
<TextView
android:id="@+id/tags_formatted"
style="@style/FormattedTitleValue"/>
<include
android:id="@+id/comment_formatted"
layout="@layout/formatted_title_value"/>
<include
android:id="@+id/locations_formatted"
layout="@layout/formatted_title_value"/>
<include
android:id="@+id/criteria_formatted"
layout="@layout/formatted_title_value"/>
<include
android:id="@+id/facts_formatted"
layout="@layout/formatted_title_value"/>
<include
android:id="@+id/images_formatted"
layout="@layout/formatted_title_data"/>
</LinearLayout>
</ScrollView>
编辑:这里是 activity 和片段:
Activity
public class ActivityFormatReview extends FragmentActivity implements LaunchableUi,
OptionSelectListener, FormattedPagerAdapter.FragmentsObserver {
private static final String TAG = TagKeyGenerator.getTag(ActivityFormatReview.class);
private static final String RETAIN_VIEW
= TagKeyGenerator.getKey(ActivityFormatReview.class, "RetainView");
private static final int LAYOUT = R.layout.view_pager;
private static final int PAGER = R.id.pager;
private FormattedPagerAdapter mAdapter;
private ViewPager mPager;
private FragmentInitialiser mInitialiser;
public ReviewNode getNode(ReviewId id) {
return mAdapter.getNode(id);
}
public void remove(FragmentFormatReview fragment) {
mAdapter.removeFragment(fragment);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(LAYOUT);
Bundle args = getIntent().getBundleExtra(getLaunchTag());
if (args == null) throwNoReview();
AppInstanceAndroid app = AppInstanceAndroid.getInstance(this);
ReviewNode node = app.unpackNode(args);
if (node == null) throwNoReview();
boolean isPublished = NodeLauncher.isPublished(args);
mPager = findViewById(PAGER);
mAdapter = new FormattedPagerAdapter(node, new NodeComparatorMostRecent(),
getSupportFragmentManager(), this, isPublished);
mPager.setAdapter(mAdapter);
mInitialiser = new FragmentInitialiser(app.getUi());
mPager.addOnLayoutChangeListener(mInitialiser);
mPager.addOnPageChangeListener(mInitialiser);
}
@Override
public void onNoFragmentsLeft() {
finish();
}
@Override
public void updateTitle(String title) {
mInitialiser.setTitle(title);
}
@Override
protected void onDestroy() {
super.onDestroy();
mAdapter.detach();
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(RETAIN_VIEW, true);
super.onSaveInstanceState(outState);
}
@Override
public String getLaunchTag() {
return TAG;
}
@Override
public void launch(UiTypeLauncher launcher) {
launcher.launch(getClass(), getLaunchTag());
}
@Override
public boolean onOptionSelected(int requestCode, String option) {
FragmentFormatReview fragment = getVisibleFragment();
return fragment != null && fragment.onOptionSelected(requestCode, option);
}
@Override
public boolean onOptionsCancelled(int requestCode) {
FragmentFormatReview fragment = getVisibleFragment();
return fragment != null && fragment.onOptionsCancelled(requestCode);
}
@Override
protected void onResume() {
super.onResume();
AppInstanceAndroid.setActivity(this);
}
@Nullable
private FragmentFormatReview getVisibleFragment() {
return mAdapter.getFragment(mPager.getCurrentItem());
}
private void throwNoReview() {
throw new RuntimeException("No review found");
}
private class FragmentInitialiser implements ViewPager.OnLayoutChangeListener, ViewPager
.OnPageChangeListener {
private UiSuite mUi;
private FragmentInitialiser(UiSuite ui) {
mUi = ui;
}
@Override
public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int
i6, int i7) {
setTitle();
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
setTitle();
}
@Override
public void onPageScrollStateChanged(int state) {
}
private void setTitle() {
FragmentFormatReview fragment = getVisibleFragment();
if (fragment != null) {
setTitle(fragment.isPublished() ?
mAdapter.getTitle(fragment) : Strings.Screens.PREVIEW);
}
}
private void setTitle(String title) {
mUi.getCurrentScreen().setTitle(title);
}
}
}
片段
public class FragmentFormatReview extends PagerAdapterBasic.PageableFragment implements
ReviewNode.NodeObserver,
DataReference.InvalidationListener,
OptionSelectListener {
private static final String ID = TagKeyGenerator.getKey(FragmentFormatReview.class,
"ReviewId");
private static final String PUBLISHED = TagKeyGenerator.getKey(FragmentFormatReview.class,
"published");
private static final int LAYOUT = R.layout.fragment_review_formatted;
private static final int IMAGE = R.id.image_formatted;
private static final int SUBJECT = R.id.subject_formatted;
private static final int RATING = R.id.rating_formatted;
private static final int HEADLINE = R.id.headline_formatted;
private static final int STAMP = R.id.stamp_formatted;
private static final int COMMENT = R.id.comment_formatted;
private static final int TAGS = R.id.tags_formatted;
private static final int CRITERIA = R.id.criteria_formatted;
private static final int FACTS = R.id.facts_formatted;
private static final int LOCATIONS = R.id.locations_formatted;
private static final int IMAGES = R.id.images_formatted;
private static final int DATA = R.id.section_data;
private static final int IMAGE_PADDING = R.dimen.formatted_image_padding;
private static final int IMAGE_PLACEHOLDER = R.drawable.image_placeholder;
private static final ReviewViewParams.CellDimension FULL
= ReviewViewParams.CellDimension.FULL;
private static final ReviewViewParams.CellDimension HALF
= ReviewViewParams.CellDimension.HALF;
private boolean mIsPublished = true;
private ReviewNode mNode;
private UiSuite mUi;
private RepositorySuite mRepo;
private MenuUi mMenu;
private CoverNodeBannerUi mCover;
private ViewUi<TextView, String> mSubject;
private ViewUi<RatingBar, Float> mRating;
private ViewUi<TextView, RefDataList<DataTag>> mTags;
private ViewUi<TextView, AuthorReference> mStamp;
private FormattedSectionUi<RefCommentList> mComment;
private FormattedSectionUi<RefDataList<DataCriterion>> mCriteria;
private FormattedSectionUi<RefDataList<DataFact>> mFacts;
private FormattedSectionUi<RefDataList<DataLocation>> mLocations;
private FormattedSectionUi<ReviewItemReference<DataSize>> mImages;
public static FragmentFormatReview newInstance(String nodeId, boolean isPublished) {
//Can't use FactoryFragment as Support fragment rather than normal fragment
Bundle args = new Bundle();
args.putString(ID, nodeId);
args.putBoolean(PUBLISHED, isPublished);
FragmentFormatReview fragment = new FragmentFormatReview();
fragment.setArguments(args);
return fragment;
}
public boolean isPublished() {
return mIsPublished;
}
@Override
public String getPageId() {
return mNode.getReviewId().toString();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
setHasOptionsMenu(true);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
AppInstanceAndroid app = AppInstanceAndroid.getInstance(getContext());
mUi = app.getUi();
mRepo = app.getRepository();
View v = inflater.inflate(LAYOUT, container, false);
Bundle args = getArguments();
if (args == null) {
noReview();
return v;
}
mIsPublished = args.getBoolean(PUBLISHED);
setNode(args);
setMenu();
setCover(v);
setSubject(v);
setRating(v);
setStamp(v);
setComment(v);
setTags(v);
setCriteria(v);
setFacts(v);
setLocations(v);
setImages(v);
return v;
}
@Override
public void onCreateOptionsMenu(Menu menu, android.view.MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
mMenu.inflate(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(android.view.MenuItem item) {
return mMenu.onItemSelected(item) || super.onOptionsItemSelected(item);
}
@Override
public void onChildAdded(ReviewNode child) {
update();
}
@Override
public void onChildRemoved(ReviewNode child) {
update();
}
@Override
public void onNodeChanged() {
update();
}
@Override
public void onTreeChanged() {
update();
}
@Override
public boolean onOptionSelected(int requestCode, String option) {
return mMenu.onOptionSelected(requestCode, option);
}
@Override
public boolean onOptionsCancelled(int requestCode) {
return mMenu.onOptionsCancelled(requestCode);
}
@Override
public void onResume() {
super.onResume();
update();
}
@Override
public void onDestroyView() {
super.onDestroyView();
mNode.unregisterObserver(this);
}
@Override
public void onReferenceInvalidated(DataReference<?> reference) {
if (getContainer() != null) getContainer().remove(this);
}
private FactoryCommands getCommandsFactory() {
return mUi.getCommandsFactory();
}
private ConverterGv getConverter() {
return mUi.getGvConverter();
}
private ActivityFormatReview getContainer() {
try {
return (ActivityFormatReview) getActivity();
} catch (ClassCastException e) {
throw new RuntimeException(e);
}
}
private void noReview() {
AppInstanceAndroid app = AppInstanceAndroid.getInstance(getContext());
CurrentScreen currentScreen = app.getUi().getCurrentScreen();
currentScreen.showToast(Strings.Toasts.REVIEW_NOT_FOUND);
currentScreen.close();
}
private void setNode(Bundle args) {
String reviewId = args.getString(ID);
if (reviewId == null) {
noReview();
return;
}
mNode = getContainer().getNode(new DatumReviewId(reviewId));
mNode.registerObserver(this);
ReviewReference reference = mNode.getReference();
if (mNode.isLeaf() && reference != null) reference.registerListener(this);
}
private void setMenu() {
AppInstanceAndroid app = AppInstanceAndroid.getInstance(getContext());
UiSuite ui = app.getUi();
MenuActionItem<GvData> upAction = new MaiUpAppLevel<>(app);
MenuAction<?> action;
if (mIsPublished) {
OptionsCommand command
= getCommandsFactory().newReviewOptionsSelector(ReviewOptionsSelector
.SelectorType.ALL, new NodeAuthorId(mNode));
MaiOptionsCommand<GvData> mai = new MaiOptionsCommand<>(command);
action = new MenuOptionsAppLevel(Strings.Menu.REVIEWS, upAction, mai, ui);
} else {
action = new MenuUpAppLevel(Strings.Screens.PREVIEW, upAction, ui);
}
mMenu = new MenuUi(action);
}
private void update() {
mCover.update();
mImages.update();
mSubject.update();
mRating.update();
mStamp.update();
mTags.update();
mComment.update();
mLocations.update();
mCriteria.update();
mFacts.update();
}
@Nullable
private Command launchView(GvDataType<?> type) {
return mIsPublished ? newLaunchViewCommand(type) : null;
}
private void setCover(View v) {
CellDimensionsCalculator calculator = new CellDimensionsCalculator(getActivity());
CellDimensionsCalculator.Dimensions dims = calculator.calcDimensions(FULL, FULL, 0);
Bitmap placeholder = BitmapFactory.decodeResource(getResources(), IMAGE_PLACEHOLDER);
mCover = new CoverNodeBannerUi((ImageView) v.findViewById(IMAGE), mNode,
mRepo.getAuthorsRepo().getProfile(mNode.getAuthorId()).getProfileImage(),
placeholder, dims);
setLaunchOnClick(mCover, getCommandsFactory().newLaunchBespokeViewCommand(mNode,
"Images", GvImage.TYPE));
}
private void setSubject(View v) {
mSubject = new SubjectNodeUi((TextView) v.findViewById(SUBJECT), mNode, null);
}
private void setRating(View v) {
mRating = new RatingBarTouchable((RatingBar) v.findViewById(RATING), mNode, null);
}
private void setStamp(View v) {
mStamp = new StampNodeUi((TextView) v.findViewById(STAMP), mNode, mRepo.getAuthorsRepo());
setLaunchOnClick(mStamp, launchAuthor());
}
private void setTags(View v) {
mTags = new TagsNodeUi((TextView) v.findViewById(TAGS), mNode);
setLaunchOnClick(mTags, GvTag.TYPE);
}
private void setComment(View v) {
mComment = new CommentNodeUi(getSection(v, COMMENT), (TextView) v.findViewById(HEADLINE),
mNode, launchView(GvComment.TYPE));
}
private void setLocations(View v) {
mLocations = newDataUi(v, LOCATIONS, Strings.Formatted.LOCATIONS, GvLocation.TYPE,
getConverter().newConverterLocations(), VhLocationFormatted.class,
new SimpleViewUi.ReferenceValueGetter<RefDataList<DataLocation>>() {
@Override
public RefDataList<DataLocation> getValue() {
return mNode.getLocations();
}
});
}
private void setCriteria(View v) {
mCriteria = newDataUi(v, CRITERIA, Strings.Formatted.CRITERIA, GvCriterion.TYPE,
getConverter().newConverterCriteria(), VhCriterionFormatted.class,
new SimpleViewUi.ReferenceValueGetter<RefDataList<DataCriterion>>() {
@Override
public RefDataList<DataCriterion> getValue() {
return mNode.getCriteria();
}
});
}
private void setFacts(View v) {
mFacts = newDataUi(v, FACTS, Strings.Formatted.FACTS, GvFact.TYPE,
getConverter().newConverterFacts(), VhFactFormatted.class,
new SimpleViewUi.ReferenceValueGetter<RefDataList<DataFact>>() {
@Override
public RefDataList<DataFact> getValue() {
return mNode.getFacts();
}
});
}
private void setImages(View v) {
LinearLayout section = getSection(v, IMAGES);
RecyclerView grid = section.findViewById(DATA);
float padding = getResources().getDimensionPixelSize(IMAGE_PADDING);
CellDimensionsCalculator calculator = new CellDimensionsCalculator(getActivity());
CellDimensionsCalculator.Dimensions dims = calculator.calcDimensions(HALF, HALF, (int)
padding);
ViewUi<RecyclerView, RefDataList<DataImage>> dataView = newGridUi
(grid, VhImage.class, 1, (int) padding, dims, getConverter().newConverterImages(),
new SimpleViewUi.ReferenceValueGetter<RefDataList<DataImage>>() {
@Override
public RefDataList<DataImage> getValue() {
return mNode.getImages();
}
});
mImages = new ImagesNodeUi(section, dataView, mNode);
}
private void setLaunchOnClick(ViewUi<?, ?> layout, GvDataType<?> type) {
Command onClick = launchView(type);
setLaunchOnClick(layout, onClick);
}
private void setLaunchOnClick(ViewUi<?, ?> layout, @Nullable Command onClick) {
if (mIsPublished && onClick != null) layout.setOnClickCommand(onClick);
}
private <T1 extends HasReviewId, T2 extends GvData, Vh extends ViewHolder>
ViewUi<RecyclerView, RefDataList<T1>>
newGridUi(RecyclerView view, Class<Vh> vhClass,
int span, int padding, CellDimensionsCalculator.Dimensions dims,
DataConverter<T1, T2, ? extends GvDataList<T2>> converter,
SimpleViewUi.ReferenceValueGetter<RefDataList<T1>> getter) {
IdableDataList<T1> empty = new IdableDataList<>(getter.getValue().getReviewId());
GvDataType<T2> dataType = converter.convert(empty).getGvDataType();
GvDataRefAdapter<T1, T2, Vh> adapter
= new GvDataRefAdapter<>(getter, converter, new VhFactory<>(vhClass), dims);
Command onClick = mIsPublished ? newLaunchViewCommand(dataType) : null;
view.addItemDecoration(new PaddedItemDecoration(padding));
return new HorizontalGridUi<>(getContext(), view, adapter, span, onClick);
}
private Command newLaunchViewCommand(GvDataType<?> dataType) {
return getCommandsFactory().newLaunchViewCommand(mUi.newDataView(mNode, dataType));
}
private Command launchAuthor() {
return mUi.getCommandsFactory().newLaunchAuthorCommand(mNode.getAuthorId());
}
private <T extends HasReviewId, G extends GvData> DataExpandableUi<T>
newDataUi(View v, int sectionId, String title, GvDataType<G> dataType,
DataConverter<T, G, ?> converter, Class<? extends ViewHolder> vhClass,
SimpleViewUi.ReferenceValueGetter<RefDataList<T>> getter) {
DataExpandableUi<T> ui = new DataExpandableUi<>(getContext(), getSection
(v, sectionId), title, getter, newVhFactory(vhClass), converter);
setLaunchOnClick(ui, dataType);
return ui;
}
@NonNull
private ViewHolderFactory<ViewHolder> newVhFactory(final Class<? extends ViewHolder> vhClass) {
return new ViewHolderFactory<ViewHolder>() {
@Override
public ViewHolder newViewHolder() {
try {
return vhClass.newInstance();
} catch (java.lang.InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
};
}
private LinearLayout getSection(View v, int id) {
return (LinearLayout) v.findViewById(id);
}
private static class NodeAuthorId extends DatumAuthorId {
private ReviewNode mNode;
private NodeAuthorId(ReviewNode node) {
super(node.getReviewId(), node.getAuthorId().toString());
mNode = node;
}
@Override
public ReviewId getReviewId() {
return mNode.getReviewId();
}
@Override
public String toString() {
return mNode.getAuthorId().toString();
}
}
private static class PaddedItemDecoration extends RecyclerView.ItemDecoration {
private final int mPadding;
PaddedItemDecoration(int padding) {
mPadding = padding;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
outRect.right = mPadding;
}
}
}
编辑 2:这是清单条目:
<activity
android:name=".ApplicationPlugins.PlugIns.UiPlugin.UiAndroid.Implementation.Act
ivities.ActivityFormatReview"
android:configChanges="orientation"
android:exported="true"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan" >
</activity>
在您的滚动视图上设置背景
在XML:
android:background="@color/Your_White_Color"
变成这样
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scroll_formatted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:background="@color/Your_White_Color">
或在代码中:
ScrollView scrollView = (ScrollView) findViewById(R.id.scroll_formatted);
scrollView.setBackground(R.color.Your_White_Color);
应该是不错的打印屏幕,从视图上更好理解
受到 Patrick R. 评论的启发,我尝试将背景设置为纯色的可绘制对象。在发布我的问题之前,我曾尝试直接设置颜色,但没有成功。也没有将滚动视图包装在框架布局中。但是,将背景设置为纯色的可绘制对象似乎可以解决问题
滚动视图:
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scroll_formatted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:background="@drawable/background">
background.xml
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?dominantBackground" />
</shape>
我完全不知道为什么会这样,所以不能肯定地说它是否在所有情况下都解决了问题,但它确实解决了我能够重复产生问题的情况。