7

異なる行レイアウト テンプレートを使用したリスト ビューごとに、同じことを行うカスタム アダプターを作成する必要があります。xml 行レイアウトを読み込み、ID でコントロール (TextView、ImageView など) を取得し、データを表示します。このようなものです。 :

public class CommentAdapter extends BaseAdapter {

protected Activity activity;
protected static LayoutInflater layoutInflater = null;  
protected List<Comment> lst;    

public CommentAdapter(Activity activity,  List<Comment> lst){
    this.activity = activity;       
    this.lst = lst;
    layoutInflater = (LayoutInflater)this.activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

public int getCount() {     
    return lst.size();
}

public Object getItem(int position) {   
    return lst.get(position);
}

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

public static class ViewHolder{
    public TextView textName;
    public TextView textComment;
    public ImageView image;
}

public  View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    ViewHolder viewHolder;
    if (v == null) {
        v = layoutInflater.inflate(R.layout.listitem, null);
        viewHolder = new ViewHolder();
        viewHolder.textName = (TextView) v.findViewById(R.id.txtName);
        viewHolder.image = (ImageView) v.findViewById(R.id.icon);
        viewHolder.textComment = (TextView)v.findViewById(R.id.txtComment);
        v.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) v.getTag();
    }
    Static.overrideFonts(v);
    viewHolder.image.setBackgroundResource(lst.get(position).Icon);
    viewHolder.textName.setText(lst.get(position).Name);
    viewHolder.textComment.setText(lst.get(position).Comment);

    return v;
}
}

多くの種類のリスト ビュー (差分行レイアウト テンプレート) では、多くのアダプターを作成する必要があります。
したがって、問題は、行 xml を動的にロードし、その ID に基づいてビュー コントロールをマップすることができる 1 つのテンプレート アダプターを作成することです (おそらくリフレクトを使用します)。行 xml レイアウト、コントロール ID、ビュー コントロールは別の場所で定義されます。
はありますかdesign patternexampleまたはframeworkこれを達成できますか?

4

2 に答える 2

8

このようなことは実行可能のようです。私はこれをまったくテストしていませんが、理論的には、次のようなものでうまくいく可能性があります。

public interface Adaptable {
    //Interface that any object you make that should be put in a listview
    //should implement
    public View buildView(View v, LayoutInflater inflater);
    public int getLayoutId();
}

public class MyObject implements Adaptable
    //Just hardcode your layout for this type of object
    public int getLayoutId() {
        return R.layout.myLayout;
    }

    //getView() will pass the recycled view to this method
    //which will handle building the view per this object
    public View buildView(View v, LayoutInflater inflater) {
        if(v == null) {
            v = inflater.inflate(getLayoutId());
            //Other initialization
        } //other initialization

        return v;
    }
}

//Then make the generic adapter that handles anything that implements
//the Adaptable interface
public GenericAdapter implements ListAdapter {
    private LayoutInflater inflater;
    private List<Adaptable> items;
    public GenericAdapter(List<Adaptable> items, Context c) {
        this.items = items;
        inflater = LayoutInflater.from(c);
    }

    //Now, using polymorphism, it should return a correctly built
    //view for whatever object type you've passed in.
    @Override
    public View getView(int pos, View convertView, ViewGroup parent) {
        return items.get(pos).buildView(convertView, inflater);
    }
}

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    List<MyObject> objects = new ArrayList<MyObject>();
    //Fill your list however.

    //get your ListView, then...
    listView.setAdapter(new GenericAdapter(object, this));
}

これが機能しない何らかの理由を完全に見落としている可能性があります.5分でこれをタイプしました. 理論的には、うまくいくと思いますが。

于 2012-10-24T19:22:10.297 に答える
2

私はkcoppockの方法を試しましたが、もう少し複雑です。
まず、アノテーションを使用してビュー ID にマップできる ViewHolder を作成します。

public class MobileViewHolder {

    @InvokeView(viewId = R.id.label)
    public TextView text;

    @InvokeView(viewId = R.id.logo)
    public ImageView image;
}

次に、reflect を使用して ViewHolder のフィールドをビュー ID にマップできます。

   Field fs[] = viewHolder.getClass().getFields();
        for (Field f : fs) {
            InvokeView a = (InvokeView)f.getAnnotation(InvokeView.class);
            int id = a.viewId();
            f.set(viewHolder, v.findViewById(id));

    }

その後、エンティティから ViewHolder にデータをバインドするだけです。

  public void mappingData(MobileViewHolder viewHolder, Mobile entity) {
    viewHolder.text.setText(entity.name);
    viewHolder.image.setBackgroundResource(entity.image);
}

結論: このように、行レイアウト テンプレートが異なる多くの種類のリスト ビューでは、必要なものは 4 つだけです。

  • 行 xml ファイル
  • ViewHolder: ビュー コントロールとビュー プロパティを定義します。
  • 実在物
  • アイテム ビュー: BaseView と、ViewHolder と Entity の間のマッピング ロジック データを拡張します。

そして、これが私がテストしたソースコードのサンプルです:)

于 2012-10-25T18:34:49.093 に答える