DialogFragment中带有LinearLayouts的ListView不会包装内容

时间:2017-11-02 20:41:53

标签: android android-layout listview android-dialogfragment

我在Android中构建了一个易于构建和构建的构造。在屏幕上显示DialogFragment。 该对话框包含TextView,ListView和Button。 它可以轻松地在ListView中扩展不同的视图,因此我可以创建自定义对话框。

实施例: enter image description here

左图是正确的。在右边,我夸大了一个额外的视图。我用来在DialogFragment中显示文本的视图。但是当我添加该视图时,它不再包装内容。 ListView使其自身可滚动。

我可以添加更多您在图像上看到的蓝色按钮,ListView仍然会正确包装内容。但是当我添加一个或多个其他视图时,ListView使其自身可滚动。

问题是我无法让ListView以wrap_content正确。

这是“蓝色按钮”视图的xml :(正确的膨胀视图)

 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/overlay_item_label"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:layout_weight="1"
     android:orientation="vertical"
     android:weightSum="1">

     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:background="@drawable/tile_button_categorytile"
         android:orientation="horizontal">

         <ImageView
             android:id="@+id/popUpImage"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:layout_margin="6dp"
             android:scaleType="fitCenter"
             android:src="@drawable/ic_speaker" />

        <com.joanzapata.iconify.widget.IconTextView
             android:id="@+id/popUpButton"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_gravity="center"
             android:layout_margin="4dp"
             android:layout_marginRight="15dp"
             android:layout_weight="1"
             android:padding="4dp"
             android:text="Bewerken {fa-android}"
             android:textColor="@color/white"
             android:textSize="14sp"
             android:textStyle="bold" />
    </LinearLayout>
</LinearLayout>

在DialogFragment中用作文本的视图:(导致ListView使其自身可滚动)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/overlay_item_label"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"

    android:background="@color/white"
    android:layout_weight="1"
    android:weightSum="1">

        <TextView
            android:id="@+id/LabelOverlay"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:layout_gravity="center"
            android:gravity="center"
            android:paddingLeft="5dp"
            android:paddingRight="5dp"
            android:text="@string/placeholder"
            android:textColor="@color/purple"
            android:textSize="12sp" />
</LinearLayout>

当我向用于显示文本的视图添加额外的paddingTop和paddingBottom时,ListView不会使其自身可滚动(仅在少数设备上)。填充设置为大约20dp然后在某些设备上它不会使自己可滚动,但在其他设备上它的填充太多,所以它显示空白...

这是显示DialogFragment的片段代码:

public class PopUpFragmentPhone extends DialogFragment {
    PopUp popUpData;
    ListView listView;

    public static PopUpFragmentPhone newInstance(PopUp data) {
        PopUpFragmentPhone popUpFragment = new PopUpFragmentPhone();

        Bundle args = new Bundle();
        args.putParcelable("PopUpData", data);
        popUpFragment.setArguments(args);
        return popUpFragment;
    }

    @Override
    public void onStart(){
        super.onStart();
        Window window = getDialog().getWindow();
        WindowManager.LayoutParams windowParams = window.getAttributes();
        windowParams.dimAmount = 0.70f;

        windowParams.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
        window.setAttributes(windowParams);

        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

        getDialog().getWindow().setLayout(MainApplication.width / 2, ViewGroup.LayoutParams.WRAP_CONTENT);
        getDialog().setCanceledOnTouchOutside(true);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme);
        popUpData = getArguments().getParcelable("PopUpData"); //get the PopUp class.
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.pop_up_phone, container, false);

        //Set the title of the popUp
        TextView popUpTitle = (TextView)v.findViewById(R.id.overlayTitle);
        popUpTitle.setText(popUpData.getHeader());

        listView = (ListView) v.findViewById(R.id.listViewItemsOverlay);
        listView.setAdapter(new PopUpAdapterPhone(MainApplication.getContext(), 1, popUpData.getItems(), this));

        boolean showCancel = popUpData.isCancel();
        Button cancelButton = (Button) v.findViewById(R.id.cancel_button);
        Drawable cancelIcon = new IconDrawable(getActivity(), FontAwesomeIcons.fa_times).colorRes(R.color.red).sizeDp(20);
        cancelButton.setCompoundDrawablesWithIntrinsicBounds(cancelIcon, null, null, null);
        if(showCancel) {
            // Cancel button click
            cancelButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    getDialog().dismiss();
                }
            });
        } else {
            cancelButton.setVisibility(View.GONE);
        }

        getDialog().getWindow().setLayout(MainApplication.width / 2, ViewGroup.LayoutParams.WRAP_CONTENT);//set the size of the fragment, so the rest is a touch to cancel the popUP

        return v;
    }
}

弹出片段的视图:

<?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical"
      android:gravity="center"
      android:padding="5dp"
      android:weightSum="3"
      android:background="@drawable/tile_button_wordtile"
      android:id="@+id/overlay_master_view">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/menu"
            android:id="@+id/overlayTitle"
            android:textStyle="bold"
            android:textSize="15sp"
            android:padding="4dp"
            android:textColor="@color/purple"
            android:layout_weight="1"
            android:background="@color/white"
            android:layout_margin="4dp"
            android:layout_gravity="center_horizontal" />

       <ListView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scrollbars="none"
            android:layout_weight="1"
            android:divider="@android:color/transparent"
            android:dividerHeight="5.0sp"
            android:id="@+id/listViewItemsOverlay">

        </ListView>

        <com.joanzapata.iconify.widget.IconButton
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="start"
            android:padding="5dp"
            android:layout_weight="1"
            android:textStyle="bold"
            android:textSize="15sp"
            android:drawablePadding="5dp"
            android:id="@+id/cancel_button"
            android:layout_marginTop="5dp"
            android:textColor="@color/red"
            android:background="@drawable/tile_button_functiontile"
            android:text="@string/cancel"/>
 </LinearLayout>

我尝试了很多东西,在LinearLayout或RelativeLayout中充气。 Wrap_content,match_parent,weightSum和所有类型的东西。尝试在很多方面改变布局,但一切都没有成功。

我希望有人可以帮助我。

1 个答案:

答案 0 :(得分:1)

注意:在下面的代码中,我删除了背景,因为我没有。

但基本上你不应该过多地改变它以匹配你想要的东西。

您的对话

import android.app.Dialog;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.view.WindowManager;
import android.widget.ListView;

import java.util.ArrayList;

public class CustomDialogFragment extends DialogFragment {

    private static final String DIALOG_DATA = "my.app.package.DIALOG_DATA";

    public static CustomDialogFragment newInstance(ArrayList<ListElement> data) {
        CustomDialogFragment f = new CustomDialogFragment();
        Bundle args = new Bundle();
        args.putParcelableArrayList(DIALOG_DATA, data);
        f.setArguments(args);

        return f;
    }

    @Override
    public void onResume() {
        super.onResume();
        // Calculate the height/width you want
        // See: https://stackoverflow.com/a/12923805/1827254 for more info
        // In this example, the width is not changed as retrieved from the LayoutParams of the dialog.

        WindowManager.LayoutParams params = getDialog().getWindow().getAttributes();
        int width = params.width; //getResources().getDimensionPixelSize(R.dimen.popup_width);
        int height = getResources().getDimensionPixelSize(R.dimen.popup_height);

        getDialog().getWindow().setLayout(width, height);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        ArrayList<ListElement> data = getArguments().getParcelableArrayList(DIALOG_DATA);

        // Inflate the dialog layout
        View view = View.inflate(getContext(), R.layout.custom_dialog, null);

        ListView listView = view.findViewById(R.id.dialog_list);
        listView.setAdapter(new CustomAdapter(getContext(), data));

        View btn = view.findViewById(R.id.dialog_cancel_button);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                dismiss(); // Dismiss the dialog.
            }
        });

        return new AlertDialog.Builder(getActivity())
                .setView(view)
                .create();
    }
}

对话框布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/overlay_master_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp">

    <!-- Title of the view -->

    <!-- Note: instead of using 'android:text="@string/placehoder"' use
         'tools:text="My preview text"'. Otherwise the system has to set your
         placeholder value and then replace it with the actual value you want in the code -->
    <TextView
        android:id="@+id/dialog_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:background="@color/white"
        android:padding="4dp"
        android:text="@string/menu"
        android:textColor="@color/purple"
        android:textSize="15sp"
        android:textStyle="bold"
        tools:text="Preview text" />

    <!-- The ListView needs to have a height of 0 in order to let
    the button to be displayed below it-->
    <ListView
        android:id="@+id/dialog_list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:divider="@android:color/transparent"
        android:dividerHeight="5.0sp"
        android:scrollbars="none" />

    <!-- Button 'cancel'-->
    <com.joanzapata.iconify.widget.IconButton
        android:id="@+id/dialog_cancel_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:drawablePadding="5dp"
        android:gravity="start"
        android:padding="5dp"
        android:text="@string/cancel"
        android:textColor="@color/red"
        android:textSize="15sp"
        android:textStyle="bold" />
</LinearLayout>

列表适配器

 class CustomAdapter extends ArrayAdapter<ListElement> {
    private final LayoutInflater mInflater;

    public CustomAdapter(Context context, ArrayList<ListElement> data) {
        super(context, 0, data);
        mInflater = LayoutInflater.from(context);
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, @NonNull ViewGroup parent) {
        // Get the data item for this position
        ListElement element = getItem(position);
        // Check if an existing view is being reused, otherwise inflate the view
        if (convertView == null) {
            // Use your custom layout
            convertView = mInflater.inflate(R.layout.list_element, parent, false);
        }

        // Get the views and set the data

        TextView tv = (TextView) convertView.findViewById(R.id.elt_text);
        tv.setText(element.getText());

        ImageView imageView = (ImageView) convertView.findViewById(R.id.elt_image);
        imageView.setImageResource(element.getIconRes());

        return convertView;
    }
}

列出元素布局

我认为为每个组件设置权重是您的一个问题

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/overlay_item_label"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/blue"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/elt_image"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_margin="6dp"
        android:scaleType="fitCenter"
        tools:src="@mipmap/ic_launcher" />

    <com.joanzapata.iconify.widget.IconTextView
        android:id="@+id/elt_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:layout_margin="4dp"
        android:layout_marginRight="15dp"
        android:padding="4dp"
        android:textColor="@color/white"
        android:textSize="14sp"
        android:textStyle="bold"
        tools:text="Bewerken {fa-android}" />
</LinearLayout>

列表中的元素

import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.DrawableRes;

/**
 * Every element of the list has an icon and a text.
 * You can add other parameters
 */

public class ListElement implements Parcelable {
    private String mText;
    @DrawableRes
    private Integer mIconRes;

    public ListElement() {
        // Default constructor
    }

    public ListElement(String text, @DrawableRes int resId) {
        this.mText = text;
        this.mIconRes = resId;
    }

    protected ListElement(Parcel in) {
        mText = in.readString();
        if (in.readByte() == 0) {
            mIconRes = null;
        } else {
            mIconRes = in.readInt();
        }
    }

    public static final Creator<ListElement> CREATOR = new Creator<ListElement>() {
        @Override
        public ListElement createFromParcel(Parcel in) {
            return new ListElement(in);
        }

        @Override
        public ListElement[] newArray(int size) {
            return new ListElement[size];
        }
    };

    public String getText() {
        return mText;
    }

    public Integer getIconRes() {
        return mIconRes;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(mText);
        if (mIconRes == null) {
            parcel.writeByte((byte) 0);
        } else {
            parcel.writeByte((byte) 1);
            parcel.writeInt(mIconRes);
        }
    }
}

用例示例(在MainActivity中)

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();

        ArrayList<ListElement> data = generateData();

        // Create and show the dialog.
        DialogFragment newFragment = CustomDialogFragment.newInstance(data);
        newFragment.show(ft, "dialog");
    }

    private ArrayList<ListElement> generateData() {
        ArrayList<ListElement> list = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            list.add(new ListElement("elt " + i, R.mipmap.ic_launcher));
        }

        return list;
    }
}