Android 可滚动布局

Posted

技术标签:

【中文标题】Android 可滚动布局【英文标题】:Android scrollable layout 【发布时间】:2016-12-02 03:42:28 【问题描述】:

我想将按钮放在 ListView 下方,并将所有内容都放在 ScrollView 中(不仅 ListView 应该是可滚动的,而且按钮也是如此,所以如果 ListView 有很多元素,按钮是不可见的,用户必须向下滚动才能单击它)。

我的 xml 是:

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

看起来像:

我不知道为什么它不起作用,有“match_parent”作为layout_hight。 我应该在我的代码中更改什么?

我的适配器:

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;
    

【问题讨论】:

【参考方案1】:

您可以使用此功能根据您的孩子设置列表视图的高度。

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

例子:

setListViewHeightBasedOnChildren(yourlistview);

【讨论】:

【参考方案2】:

ListView 可以自行滚动,不应包含在 ScrollView 中。为了您的使用,您应该做的是简单地让 ListView 保持原样,并将按钮作为 ListView 中的最后一个视图。您必须修改适配器中的 getview() 方法才能实现此目的。根据索引,您将返回一个显示 Button 的视图。

【讨论】:

我编辑了我的帖子并将适配器的代码放在那里,你能解释一下如何制作这个效果吗?【参考方案3】:

我建议你像这样使用RecyclerView with footer作为按钮,也可以试试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);
        
    

【讨论】:

以上是关于Android 可滚动布局的主要内容,如果未能解决你的问题,请参考以下文章

当softKeyBoard隐藏按钮和其他元素时如何使布局可滚动[ANDROID]

带有两个列表片段的可滚动布局

Android中包含多个可拖动列表的水平滚动

Android TextView 可滚动

当有许多子视图时,如何使相对布局可滚动?

使用约束布局或android中的任何其他方式进行垂直滚动的粘性视图