简体   繁体   中英

Android scrollable layout

I want to put button below ListView and have everything inside ScrollView(not only ListView should be scrollable but button too so if ListView has a lot of elements button is invisible and user has to scroll down to click it).

My xml is:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.plan.aplikacjamobilna.fragments.tabs.Allergies">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_gravity="center_horizontal">
            <ListView
                android:id="@+id/allergies_listView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:dividerHeight="3dp"
                android:divider="#cccccc">
            </ListView>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"/>
    </LinearLayout>
</ScrollView>

it looks like:

在此处输入图片说明

I'm not sure why it doesn't work, there is "match_parent" as layout_hight. What shuld I change in my code?

my Adapter:

public class AllergiesAdapter extends ArrayAdapter{

    List list = new ArrayList();
    char[] keys;

    public AllergiesAdapter(Context context, int resource) {
        super(context, resource);
    }

    public static class DataHandler{
        ImageView allergieIcon;
        ImageView showDetailsIcon;
        TextView allergieName;
        FrameLayout detailsLayout;
        RelativeLayout infoLayout;
        CheckBox checkBox;
    }

    @Override
    public void add(Object object) {
        super.add(object);
        list.add(object);
    }

    @Override
    public int getCount() {
        return this.list.size();
    }

    @Override
    public Object getItem(int position) {
        return this.list.get(position);
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        View view = convertView;
        final DataHandler dataHandler;
        if(convertView==null){
            LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.allergie_item,parent,false);
            dataHandler = new DataHandler();
            dataHandler.allergieIcon = (ImageView) view.findViewById(R.id.allerie_icon);
            dataHandler.showDetailsIcon = (ImageView) view.findViewById(R.id.allergie_show_info);
            dataHandler.allergieName =(TextView) view.findViewById(R.id.allerie_name);
            dataHandler.detailsLayout=(FrameLayout)view.findViewById(R.id.allergie_frameLayout);
            dataHandler.infoLayout=(RelativeLayout)view.findViewById(R.id.info_layout);
            dataHandler.checkBox=(CheckBox)view.findViewById(R.id.allergie_checkbox);
            view.setTag(dataHandler);
        }
        else{
            dataHandler=(DataHandler) view.getTag();
        }
        LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        final AllergiesDataProvider allergiesDataProvider;
        allergiesDataProvider = (AllergiesDataProvider) this.getItem(position);
        dataHandler.allergieIcon.setImageResource(allergiesDataProvider.getAllergieIcon());
        dataHandler.showDetailsIcon.setImageResource(allergiesDataProvider.getShowDetailsIcon());
        dataHandler.allergieName.setText(allergiesDataProvider.getAllergieName());
        dataHandler.showDetailsIcon.setImageResource(allergiesDataProvider.getShowDetails());

        allergiesData = getContext().getSharedPreferences("allergiesData", Context.MODE_PRIVATE);
        allergiesEditor = allergiesData.edit();

        String myKey = allergiesData.getString(ALLERIES_KEY,"00000000");
        keys = myKey.toCharArray();

        if(keys[position]=='0')
            dataHandler.checkBox.setChecked(false);
        else
            dataHandler.checkBox.setChecked(true);

        dataHandler.infoLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //   Toast.makeText(getContext(),"no elo",Toast.LENGTH_LONG).show();
                if (!allergiesDataProvider.isDetailsShows()) {
                    allergiesDataProvider.setIsDetailsShows(true);
                    LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    dataHandler.detailsLayout.removeAllViews();
                    dataHandler.detailsLayout.addView(inflater.inflate(allergiesDataProvider.getDetailsLayout(), dataHandler.detailsLayout, false));
                    dataHandler.showDetailsIcon.setImageResource(allergiesDataProvider.getHindDetails());

                } else {
                    allergiesDataProvider.setIsDetailsShows(false);
                    dataHandler.detailsLayout.removeAllViews();
                    dataHandler.showDetailsIcon.setImageResource(allergiesDataProvider.getShowDetails());
                }
            }
        });
        dataHandler.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked)
                    keys[position] = '1';
                else
                    keys[position] = '0';
                String myString = String.valueOf(keys);
                allergiesEditor.putString(ALLERIES_KEY,myString).apply();
                //Toast.makeText(getContext(),allergiesData.getString(ALLERIES_KEY,"Sd"),Toast.LENGTH_LONG).show();
            }
        });
        return view;
    }
}

You can use this function to set the height of list view based on your children.

public static void setListViewHeightBasedOnChildren(ListView listView) {
            ListAdapter listAdapter = listView.getAdapter();
            if (listAdapter == null) {
                // pre-condition
                return;
            }

            int totalHeight = 0;
            int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
            for (int i = 0; i < listAdapter.getCount(); i++) {
                View listItem = listAdapter.getView(i, null, listView);
                listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
                totalHeight += listItem.getMeasuredHeight();
            }

            ViewGroup.LayoutParams params = listView.getLayoutParams();
            params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
            listView.setLayoutParams(params);
            listView.requestLayout();
        }

Example:

setListViewHeightBasedOnChildren(yourlistview);

A ListView is scrollable on it's own and should not be wrapped in a ScrollView. For your use, what you should do is to simply have the ListView as it is and have the button as the last view in the ListView. You will have to modify the getview() method in your adapter to achieve this. Based on the index, you will return a view that displays a Button.

I suggest you to use RecyclerView with footer as a button like this way,and also try HFRecyclerView

public class HeaderFooterAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static final int TYPE_HEADER = 0;
    private static final int TYPE_ITEM = 1;
    private static final int TYPE_FOOTER = 2;

    ArrayList<Generic> generics;
    Context context;

    public HeaderFooterAdapter(Context context, ArrayList<Generic> generics) {
        this.context = context;
        this.generics = generics;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder (ViewGroup parent, int viewType) {
        if(viewType == TYPE_HEADER) {
            View v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.header_item, parent, false);
            return new HeaderViewHolder (v);
        } else if(viewType == TYPE_FOOTER) {
            View v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.footer_item, parent, false);
            return new FooterViewHolder (v);
        } else if(viewType == TYPE_ITEM) {
            View v = LayoutInflater.from (parent.getContext ()).inflate (R.layout.list_item, parent, false);
            return new GenericViewHolder (v);
        }
        return null;
    }

    private Generic getItem (int position) {
        return generics.get (position);
    }


    @Override
    public void onBindViewHolder (RecyclerView.ViewHolder holder, int position) {
        if(holder instanceof HeaderViewHolder) {
            HeaderViewHolder headerHolder = (HeaderViewHolder) holder;
            headerHolder.txtTitleHeader.setText ("Header");
            headerHolder.txtTitleHeader.setOnClickListener (new View.OnClickListener () {
                @Override
                public void onClick (View view) {
                    Toast.makeText (context, "Clicked Header", Toast.LENGTH_SHORT).show ();
                }
            });
        } else if(holder instanceof FooterViewHolder) {
            FooterViewHolder footerHolder = (FooterViewHolder) holder;
            footerHolder.txtTitleFooter.setText ("Footer");
            footerHolder.txtTitleFooter.setOnClickListener (new View.OnClickListener () {
                @Override
                public void onClick (View view) {
                    Toast.makeText (context, "Clicked Footer", Toast.LENGTH_SHORT).show ();
                }
            });
        } else if(holder instanceof GenericViewHolder) {
            Generic currentItem = getItem (position - 1);
            GenericViewHolder genericViewHolder = (GenericViewHolder) holder;
            genericViewHolder.txtName.setText (currentItem.getName ());
        }
    }

    //    need to override this method
    @Override
    public int getItemViewType (int position) {
        if(isPositionHeader (position)) {
            return TYPE_HEADER;
        } else if(isPositionFooter (position)) {
            return TYPE_FOOTER;
        }
        return TYPE_ITEM;
    }

    private boolean isPositionHeader (int position) {
        return position == 0;
    }

    private boolean isPositionFooter (int position) {
        return position == generics.size () + 1;
    }

    @Override
    public int getItemCount () {
        return generics.size () + 2;
    }

    class FooterViewHolder extends RecyclerView.ViewHolder {
        TextView txtTitleFooter;

        public FooterViewHolder (View itemView) {
            super (itemView);
            this.txtTitleFooter = (TextView) itemView.findViewById (R.id.txtFooter);
        }
    }

    class HeaderViewHolder extends RecyclerView.ViewHolder {
        TextView txtTitleHeader;

        public HeaderViewHolder (View itemView) {
            super (itemView);
            this.txtTitleHeader = (TextView) itemView.findViewById (R.id.txtHeader);
        }
    }

    class GenericViewHolder extends RecyclerView.ViewHolder {
        TextView txtName;

        public GenericViewHolder (View itemView) {
            super (itemView);
            this.txtName = (TextView) itemView.findViewById (R.id.txtName);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM