【问题标题】:Making dynamic layout for each row in ListView in android在android中为ListView中的每一行制作动态布局
【发布时间】:2014-04-06 18:13:37
【问题描述】:

我有一个 xml 文件,其中包含 ListView 每一行的基本布局(这是一个真实的布局,里面有 TextView)。

我想为 ListView 的每一行更改此布局的属性,例如每行的不同布局宽度和高度。我想动态设置宽度和高度的值。

有没有办法做到这一点?

我想要为每个视图动态更改的 xml 文件、身高和体重

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="wrap_content"
    android:id="@+id/item1"
    android:layout_width="wrap_content">
    <TextView
        android:id="@+id/text"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:text="text"
        android:visibility="visible"
        android:layout_width="wrap_content"
        android:textColor="#FF200010"
        android:background="#FFFCCCFF" />
</LinearLayout> 

我的完整文件是

package com.test.list;

import java.util.ArrayList;
import java.util.TreeSet;

import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;


public class MultipleItemsList extends ListActivity {

    private MyCustomAdapter mAdapter;

    public Context context =getApplicationContext();


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mAdapter = new MyCustomAdapter();
        for (int i = 1; i < 50; i++) {
            mAdapter.addItem("item " + i);
            if (i % 4 == 0) {
                mAdapter.addSeparatorItem("separator " + i);
            }
        }
        setListAdapter(mAdapter);
    }

    private class MyCustomAdapter extends BaseAdapter {

        private static final int TYPE_ITEM = 0;
        private static final int TYPE_SEPARATOR = 1;
        private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;

        private ArrayList<String> mData = new ArrayList<String>();
        private LayoutInflater mInflater;

        private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();

        public MyCustomAdapter() {
            mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        public void addItem(final String item) {
            mData.add(item);
            notifyDataSetChanged();
        }

        public void addSeparatorItem(final String item) {
            mData.add(item);
            // save separator position
            mSeparatorsSet.add(mData.size() - 1);
            notifyDataSetChanged();
        }

        @Override
        public int getItemViewType(int position) {
            return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
        }

        @Override
        public int getViewTypeCount() {
            return TYPE_MAX_COUNT;
        }

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

        @Override
        public String getItem(int position) {
            return mData.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            int type = getItemViewType(position);
            System.out.println("getView " + position + " " + convertView + " type = " + type);
            if (convertView == null) {
                holder = new ViewHolder();
                switch (type) {
                    case TYPE_ITEM:
                            convertView = mInflater.inflate(R.layout.item1,null);
                            Log.e("Ronak", "Here1");
                            TextView t= (TextView)convertView.findViewById(R.id.text);
                            t.setWidth(100);
                            t.setHeight(600);
                            t.setText("This is first type of view");
                            holder.textView = (TextView)convertView.findViewById(R.id.text);
                            Log.e("Ronak","reached here3");
                            break;
                    case TYPE_SEPARATOR:

                          convertView = mInflater.inflate(R.layout.item1, null);
                          TextView t2= (TextView)convertView.findViewById(R.id.text);
                            t2.setWidth(200);
                            t2.setHeight(500);
                            t2.setText("This is second type of view");
                          holder.textView = (TextView)convertView.findViewById(R.id.text);
                          break;
                }
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder)convertView.getTag();
            }
            holder.textView.setText(mData.get(position));
            return convertView;
        }

    }

    public static class ViewHolder {
        public TextView textView;
    }

}

【问题讨论】:

  • 你能分享你现有的代码吗?
  • @FaisalAli 我已经添加了我的布局文件
  • 请注意,您应该将相关参数更改为wrap_content,并动态更改文本视图的withheight
  • 删除这一行public Context context =getApplicationContext();你反正没有使用它。当你选择像这样初始化一个字段时要小心。
  • 非常感谢老兄.. 它现在工作正常:)

标签: android performance android-layout listview android-listview


【解决方案1】:

您可以为您的适配器实现ViewHolder 模式,并为每个位置扩展您自己的布局。

为此,请像这样覆盖getView

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

   // A ViewHolder keeps references to children views to avoid unneccessary calls            
  // to findViewById() on each row.            
  ViewHolder holder;            
  // When convertView is not null, we can reuse it directly, there is no need            
  // to reinflate it. We only inflate a new View when the convertView supplied            
  // by ListView is null.            

  if (convertView == null) {                

    convertView = mInflater.inflate(R.layout.sample, null);   
    // Creates a ViewHolder and store references to the two children views                
    // we want to bind data to.               
   holder = new ViewHolder();                
   holder.name = (TextView) convertView.findViewById(R.id.text);               
   holder.icon = (ImageView) convertView.findViewById(R.id.icon);                
   convertView.setTag(holder);            
 } else {                
   // Get the ViewHolder back to get fast access to the TextView                
   // and the ImageView.
   holder = (ViewHolder) convertView.getTag();
 }             


  // Bind the data efficiently with the holder. 
  holder.name.setText(myElements.get(id)); 
  holder.icon.setImageBitmap( mIcon1 );

return convertView;
}  

在 Android 开发者网站here上阅读更多相关信息

编辑:

要更改每行的宽度和高度,您可以对绑定数据部分的每一行使用类似以下的内容 :

RelativeLayout rl = (RelativeLayout) findViewById(R.id.yourId); 
rl.getLayoutParams().height = 100;
rl.getLayoutParams().width = 100;`

【讨论】:

  • 我想你没有得到我的问题。我希望动态设置布局宽度和高度,并希望为 ListView 的那一行设置 width 和 height。我想为每一行设置宽度和高度。你能进一步建议怎么做吗?
  • 我已经编辑了我的回复以阐明如何在语法上设置属性
  • 你能告诉我,把上面的代码放在 getView() 的什么地方,因为当我做同样的事情时,它给了我 RunTimeException
  • 假设您在 R.layout.sample 中有一个 xml,其中包含一个带有 id yourId 的 RelativeLayout。在您的 ViewHolder 中,您将 RelativeLayout 声明为字段,并且您有类似这样的内容:holder.relative = (RelativeLayout) convertView. findViewById(R.id.yourId); 。之后,在您的绑定数据部分中,您将拥有 holder.relative.getLayoutParams().height = 100; 这有意义吗?
  • 好的,谢谢.. 我会试试这个
【解决方案2】:

在android中为ListView中的每一行制作动态布局

也许@Arkde 的答案可能有效,但我认为这不是一个肮脏的解决方案。

如何创建一个通用布局并根据提供的条件更新/更改外观? (例如由于当前行中的值)。

每行不同的布局宽度和高度

这可以通过使用“边距”轻松实现。通过“边距”,我认为创建将作为“边距”工作的空视图,并将确定例如行的高度。然后由于提到的条件显示或隐藏它们1

通用布局有什么优势?

  • 更简单、更高效且更易于阅读的解决方案
  • 您不需要为 Adapter 实现 ViewType 和 ViewCount
  • 每行一个布局,外观多变
  • 您无需从应用程序更改 UI 外观 “硬编码”方式的逻辑

1 当 View 的可见性分配给 View.GONE 时,它不会发生在布局中,而 View.VISIBLE 会发生。

“边距”示例:

<LinearLayout>
   ...
   <View 
      android:id="@+id/upperMargin"
      android:layout_width="match_parent"
      android:layout_height="40dp"
      android:background="@android:color/transparent"
   />

   ...

   <View 
      android:id="@+id/lowerMargin"
      android:layout_width="match_parent"
      android:layout_height="40dp"
      android:background="@android:color/transparent"
   />
   ...
</LinearLayout>

注意:如果您想提高ListView 的性能,建议使用 ViewHolder 是一种非常简洁有效的方法。

我希望我的解决方案能帮助您解决您现在面临的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-12
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    • 2012-01-13
    • 1970-01-01
    相关资源
    最近更新 更多