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

时间:2014-04-06 18:13:37

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

我有一个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;
    }

}

2 个答案:

答案 0 :(得分: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;`

答案 1 :(得分:1)

  

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

也许@Arkde的答案可行,但我认为这是一个小问题。

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

  

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

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

通用布局的优点是什么?

  • 更轻松,更高效,更易读的解决方案
  • 您不需要实现ViewType和ViewCount for Adapter
  • 每行具有多变外观的一种布局
  • 您无需从应用程序更改UI外观 “硬编码”方式的逻辑

1 当视图的可见性分配给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是非常简洁有效的方法。

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