Scrollview goes black when resuming activity

时间:2018-01-15 18:22:01

标签: android android-scrollview

When I navigate away from an activity with a ScrollView then return to it, the ScrollView goes black. On launch, the colours are correct. It's just when I navigate away and come back it goes black. I have tried setting the backgrounds of the ScrollView and the internal LinearLayouts but it makes no difference. The ScrollView is inflated by a fragment in a ViewPager, in case that makes a difference.

Any ideas why this may be the case?

Here is the 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>

Edit: here is the activity and fragment:

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);
        }
    }
}

Fragment

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;
        }
    }
}

Edit 2: here is the manifest entry:

<activity            
 android:name=".ApplicationPlugins.PlugIns.UiPlugin.UiAndroid.Implementation.Act
ivities.ActivityFormatReview"
 android:configChanges="orientation"
 android:exported="true"
 android:screenOrientation="portrait"
 android:windowSoftInputMode="adjustPan" >
</activity>

2 个答案:

答案 0 :(得分:1)

受到Patrick R.评论的启发,我尝试将背景设置为纯色的可绘画。在发布我的问题之前,我曾尝试直接设置颜色,但它没有奏效。也没有将scrollview包装在framelayout中。但是,将背景设置为具有纯色的drawable似乎可以解决问题

滚动型:

<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>

我完全不知道为什么这样可行,所以不能确定它是否能在所有情况下解决问题,但它确实能够解决我能够重复生成问题的情况。

答案 1 :(得分:0)

在您的滚动视图上设置背景

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);

从视图中打印屏幕应该很好,以便更好地理解