4

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:

enter image description here

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

Aleksandar G
  • 1,163
  • 2
  • 20
  • 25
lobuli
  • 109
  • 1
  • 9
  • Possible duplicate of [Android - How do i make this alert dialog scrollable?](http://stackoverflow.com/questions/16955053/android-how-do-i-make-this-alert-dialog-scrollable) – Viral Patel Mar 28 '16 at 19:32
  • 1
    I'm not building it using AlertDialog.Builder. I'm using a custom dialog fragment. Besides, I've done what they said and it didn't work for me – lobuli Mar 28 '16 at 20:14
  • Would you post the code with wrapped scrollviewer ? – fillobotto Mar 30 '16 at 21:41
  • I pretty positive it is this line that is giving me the problem. **View view = getActivity().getLayoutInflater().inflate(R.layout.layer_legend_layout, null);** It calls the view in the for loop several times – lobuli Mar 30 '16 at 21:57
  • Try the solution in the link posted by AndroidMechanic. You should wrap your LinearLayout inside the ScrollView rather than outside it. – Mobile Developer Mar 30 '16 at 22:23
  • Tried it. Still didn't work. I posted the entire method that runs the legend. Put the entire linearlayout in a ScrollView as updated in the code and I still get the same thing. I am so confused on why it is not scrolling – lobuli Mar 31 '16 at 13:56

2 Answers2

5

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>
murt
  • 3,790
  • 4
  • 37
  • 48
1

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.

Community
  • 1
  • 1
lobuli
  • 109
  • 1
  • 9