-->

Can't Scroll in Dialog Fragment

2020-06-23 08:28发布

问题:

I am trying to get a DialogFragment to popup and to show a scrollable TextView legend but it just cuts off the rest of the legend. I can't scroll through it or anything. I tried adding a ScrollView but it doesn't do anything. This is the screen that I get:

This is my XML layout file:

<?xml version="1.0" encoding="utf-8"?>

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">

    <LinearLayout android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:scrollbars="vertical"
        android:scrollbarAlwaysDrawVerticalTrack="true"
        android:background="#fff">

        <TextView
            android:id="@+id/layer_legend_title_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:background="#fff"
            android:textColor="#000" />

        <ListView
            android:id="@+id/layer_legend_symbols_listview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:background="#fff"
            android:textColor="#000" />

    </LinearLayout>

</ScrollView>

I run this to add content to the TextView:

/**
 * A dialog that shows the legend of a ArcGISDynamicMapServiceLayer.
 */
public class LegendDialogFragment extends DialogFragment implements View.OnClickListener {

    public static final String TAG = LegendDialogFragment.class.getSimpleName();
    private LinearLayout mLinearLayout;
    private ArcGISDynamicMapServiceLayer mLayer;
    private ImageButton backButton;

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mLinearLayout = (LinearLayout) inflater.inflate(R.layout.legend_dialog_fragment_layout, null);
        getDialog().setTitle(getActivity().getString(R.string.legend));

        mLayer = ((MainActivity) getActivity()).getLayer();

        backButton = (ImageButton) mLinearLayout.findViewById(R.id.backButton2);
        backButton.setOnClickListener(this);
        // before we can show the legend we have to fetch the legend info asynchronously
        new FetchLegendTask().execute();

        return mLinearLayout;
    }

    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if (!(activity instanceof MainActivity)) {
            throw new IllegalStateException("Hosting activity needs to be of type MainActivity");
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.backButton2:
                getDialog().dismiss();
                break;
        }
    }

    /**
     * Retrieves the legend information asynchronously from the ArcGISDynamicMapServiceLayer.
     */
    private class FetchLegendTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... params) {
            mLayer.retrieveLegendInfo();
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            for (ArcGISLayerInfo layerInfo : mLayer.getAllLayers()) {
                if(layerInfo.isVisible()){
                    View view = getActivity().getLayoutInflater().inflate(R.layout.layer_legend_layout, null);
                    populateLegendView(view, layerInfo);

                    mLinearLayout.addView(view);
                }
            }
        }

        private View populateLegendView(View view, ArcGISLayerInfo layerInfo) {
            if (layerInfo != null) {
                TextView textView = (TextView) view.findViewById(R.id.layer_legend_title_textview);

                textView.setText(layerInfo.getName());
            }
            return view;
        }
    }

}

I want the entire Fragment to be scrollable but don't know how to achieve this. Whenever I try to include a ScrollView, it only scrolls the rest of that specific one line . It won't show all the content. I'm thinking it has more to do with the DialogFragment.

EDIT: Ok, so I think I know why it won't scroll. It calls the View over and over again in the loop. Then it populates the layer, and finally adds the TextView to the LinearLayout. So it is not necessarily being "appended". So adding a ScrollView will only make the last part scrollable. If anyone knows how to fix this, please let me know.

I got the link for the example from here:

MapLegend

回答1:

In dialog fragment

Maybe It's trivial, but for me it started working, after Wrapped ScrollView inside FrameLayout

Infalting DialogFragment in OnCreateView

<FrameLayout
   <ScrollView
     <ConstainLayout...>

Setting theme

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setStyle(DialogFragment.STYLE_NO_TITLE, R.style.RatingDialog2)
    }

Styles

 <style name="RatingDialog2" parent="AppTheme">
            <item name="android:windowNoTitle">true</item>
            <item name="android:windowFullscreen">true</item>
            <item name="android:windowIsFloating">true</item>
            <item name="android:windowContentOverlay">@null</item>
            <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
            <item name="android:windowSoftInputMode">adjustPan</item>
            <item name="android:windowBackground">@android:color/transparent</item>
            <item name="android:windowMinWidthMinor">90%</item>
            <item name="android:windowMinWidthMajor">60%</item>
        </style>


回答2:

I figured out how to make the entire view scrollable. The reason the ScrollView was not working was because of this statement:

mLinearLayout = (LinearLayout) inflater.inflate(R.layout.legend_dialog_fragment_layout, null);

It takes the entire layout of that xml and makes it one view. It then loops through the view and creates new views over and over again. So if you wrap the view in a scrollable, it appends the scrollable event to that specific view.

What I did was call

View view = inflater.inflate(R.layout.legend_dialog_fragment_layout, container, false);
mLinearLayout = (LinearLayout) view.findViewById(R.id.legend_dialog_fragment_linearlayout);

That way, it uses the linearLayout of that xml as opposed to the entire xml layout.

I then ran into another issue with the list being compressed into one line each time because of the ScrollView. So what I did was:

     /**** Method for Setting the Height of the ListView dynamically.
     **** Hack to fix the issue of not showing all the items of the ListView
     **** when placed inside a ScrollView  ****/
    public void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null)
            return;

        int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.UNSPECIFIED);
        int totalHeight = 0;
        View view = null;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            view = listAdapter.getView(i, view, listView);
            if (i == 0)
                view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, GridLayout.LayoutParams.WRAP_CONTENT));

            view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
            totalHeight += view.getMeasuredHeight();
        }
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
    }

which shows the list with the contents in it in one view.

By the way, I got the code from this Arshu who had an amazing solution. Here is the link:

Answer

I'm sorry if my answer seems confusing. I'm fairly new with stackoverflow and the android enviornment.