2011-12-16 10 views
15

すでにいくつかの要素が含まれているLinearLayoutビューがあります。私はプログラムで多くのビューを追加したいと思います。これはScrollViewの内部にあるため、すべてがスクロールされます。LinearLayoutに複数のビューを追加する最も簡単な方法は何ですか?

私の行うことは、私のリストを見て、私のカスタムビューの新しいインスタンスを追加することです。そのカスタムビューはXMLレイアウトを拡張し、いくつかのメソッドを追加します。

このアプローチはうまくいきます。問題は、狂ったコードがなくてもスローであることです... 10項目のリストは、インスタンス化するのに500msほどかかります。ユーザーエクスペリエンスの観点から、これは飲み込むのが難しいです。

私の質問は、正しい/最良のアプローチですか? Androidは、「R.layout.my_list_item」がシンプルであっても、レイアウトを膨らませるのに多くの時間がかかるようです。追加のビューのために "膨らんだ"レイアウトを再利用する方法があるのだろうか、もっと複雑な解析をちょっとキャッシュするのだろうか?

私はこれをListView(とアダプタとラッパー)で実行しようとしましたが、はるかに高速です。問題は私が単純なものを使うことができないということです。ListView;私のレイアウトは単純なリストよりも複雑です(LinearLayout自体には追加のカスタムアイコンが含まれていますが、それはScrollViewで囲まれる前にさらに多くのビューを持つ別の親を持っています)。

しかし、LinearLayoutにアダプタを使用する方法はありますか?ビューを自分で追加しようとするよりも速いでしょうか?

何か助けていただければ幸いです。私はこれをより速くしたいと思います。

コードが続きます。

主な活動:

// The LinearLayout that will contain everything 
lineList = (LinearLayout) findViewById(R.id.lineList); 

// Add a lot of items for testing 
for (int i = 0; i < 10; i++) { 
    addListItem("Item number " + i); 
} 

protected void addListItem(String __title) { 
    MyListItem li; 
    li = new MyListItem(this); 
    li.setTitle(__title); 
    lineList.addView(li);  
} 

MyListItem:

public class MyListItem extends RelativeLayout { 

    protected TextView textTitle; 

    public MyListItem(Context __context) { 
     super(__context); 
     init(); 
    } 

    public MyListItem(Context __context, AttributeSet __attrs) { 
     super(__context, __attrs); 
     init(); 
    } 

    public MyListItem(Context __context, AttributeSet __attrs, int __attrsdefStyle) { 
     super(__context, __attrs, __attrsdefStyle); 
     init(); 
    } 

    protected void init() { 
     // Inflate the XML layout 
     LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     inflater.inflate(R.layout.my_list_item, this); 

     // Create references 
     textTitle = (TextView)findViewById(R.id.textTitle); 
    } 

    public void setTitle(String __text) { 
     textTitle.setText(__text); 
    } 
} 

私が達成しようとしている何がこれです。このレイアウトを考える:

Basic layout

このレイアウトはFrameLayout(外箱)である(底部に、内側の長方形)ImageView(グレー)、TextView(上内側の長方形)とLinearLayoutを含みます。このLinearLayoutの四角形は、私が動的にいくつかの項目を設定しているものです。

私はそれを移入した後、私は最終的な結果は、この(すべての新しい矩形が新しいMyListItemインスタンスである場合)になりたい:

Populated layout

つまり、すべてがために、(背景画像のスクロール可能です例、上に揃えてあります)。 LinearLayoutはそれ自身ではスクロールできません(それ以外のものはすべて)。なぜ私が知っているところからListViewがうまく動作しないのでしょうか 私の場合です。

+1

あなたはそのアクティビティにいくつの要素がありますか?また、UI要素を継承したカスタマイズされたクラスを持っていますか? –

+0

リストビューはとても速いので、アイテムレイアウトをリサイクルします。彼らは、画面を埋めるために必要なアイテムレイアウトの数を膨らませます。下にスクロールすると、一番上のビューが非表示になり、一番下のビューが表示されます。リストビューは古いものから見えないものを上から取り出し、新しいデータを下に置きます。高価なインフレを避ける。全体的:これはここでは非常に非効率的なように見えますが、あなたがやりたがっていることがリストビューで達成できることは確かです。あなたが試したことを示し、意図したレイアウトのスケッチを投稿すれば、それを理解するのに役立ちます。 –

+0

Paul:多くの要素がありません。多分4または5です。はい、それらのいくつかは、基本的なフレームワークを継承するカスタムクラスです。 alextsc:説明をいただきありがとうございます。私は自分の状況をよりよく説明する図を追加したので、代わりにListViewを使用するかどうかは明らかです。 – zeh

答えて

7

3オプション:

  1. リストビューのヘッダビューなど、他の親とカスタムアイコンで、リストビューにすべてのものを交換してください。 ListViewは必要なときだけビューを作成するため、高速です。

  2. は、プログラムで使用すると、オンデマンドでのビューをロードすることを可能にするViewStubsの迅速

  3. 使用かもしれないが、代わりに膨らませるのmy_list_itemの内容を作成します。

  4. 多分、ビューだけではなくデータが読み込まれていますか?この場合、バックグラウンドスレッドでデータを準備します。

+0

これはまっすぐで実用的な応答ありがとう。私はリストに「別のスレッドでビューを作成する」を追加します(下のコメントでuser1031312が提案されています)。それ以外は、可能な解決策を十分にまとめると思います。 – zeh

1

ListViewを使用してください。

設定が簡単でメンテナンスが簡単です。 List-RowのXMLレイアウトと、List全体を保持するViewのXMLレイアウトを定義します。残りの部分はListAdapterによって処理されます。

だけ作成:地図に好きなだけアイテムを追加するために、あなたのデータによる

List<HashMap<String, String>> services = new ArrayList<HashMap<String, String>>(); 

...とループを。次に、このマップをあなたのListAdapterに設定します。 10個のアイテムか100個のアイテムかによって、ListAdapterはその多くのアイテムを含むリストを作成します。

例:

public void updateProductList(String searchTerm) { 
     createOrOpenDB(this); 
     Cursor cursor = (searchTerm!=null)? dbAdapter.fetchWhere(TBL_NAME, KEY_NAME+" LIKE '%"+searchTerm+"%'") 
       : dbAdapter.fetchAll(TBL_NAME); 
     int rows = cursor.getCount(); 
     if (rows<=0) return; 
     services.clear(); //clear current list 
     for (int i=0; i<rows; i++) { 
      HashMap<String, String> map = new HashMap<String, String>(); 
      cursor.moveToPosition(i); 
      map.put(KEY_NAME, "" + cursor.getString(cursor.getColumnIndex(KEY_NAME))); 
      map.put(KEY_DESC, "" + cursor.getString(cursor.getColumnIndex(KEY_DESC))); 
      map.put(KEY_COST, "" + cursor.getDouble(cursor.getColumnIndex(KEY_COST))); 
      services.add(map); 
     } 
     cursor.close(); 
     closeDB(); 

     ListAdapter adapter = new SimpleAdapter(this, services, R.layout.products_view_row, 
       new String[] {KEY_NAME, KEY_DESC, KEY_COST}, 
       new int[] {R.id.listViewText1, R.id.listViewText2, R.id.listViewText3}); 
     setListAdapter(adapter); 
    } 
+0

ありがとうございます。しかし、同じアプリケーションの他の部分に適切なアダプタを持つ 'ListView'を作成しました。問題は' ListView'を実装することではありません。ここでListViewを使用していない理由は、必要なもの(他の非リスト、非ヘッダー要素を並行してスクロールする)を実現していないためです。私は間違っていることを証明したいのですが、答えは "単にリストビューを使う"よりも複雑です。 – zeh

+0

わかりました。次に、これは、レイアウト全体をカプセル化するためにScrollViewと結合されたhttp://stackoverflow.com/questions/3192595/android-listview-that-does-not-scroll(受け入れられた回答を参照)です。 – Ozzy

+0

Err、元の投稿で述べたように、これはまさに私がやっていることですが、パフォーマンスに問題があります(手動でLinearLayoutにアイテムを追加するのが遅い)。 – zeh

2

ListViewは、移動するための方法です。

あなたのレイアウトは複雑すぎると言います。しかし、複雑なレイアウトを子供として膨らませることは大丈夫です。たとえば、テキストとアイコンを持っていレイアウト:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" > 
    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 
    <ImageView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 
</LinearLayout> 

はそうと、あなたのアダプタで膨張することでした:

@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    LinearLayout root = null; 
    ImageView editImageView; 

    if (convertView == null) { 
     LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     root = (LinearLayout)inflater.inflate(R.layout.item, null); 
    } else { 
     root = (LinearLayout)convertView; 
    } 
} 

ます。また、ヘッダをサポートするために、もう少し賢いことができます。索引がルートであり、別のビューを膨張させる場合は、チェックを追加するだけです。ヘッダーが異なる唯一のヘッダーなので、他のすべての行を再利用できるという利点があります。ヘッダーをあらかじめ膨張させて保管しておき、それを再利用してインフレーションを完全に取り除くこともできます。

+0

ありがとうございます。しかし、私はレイアウトが「複雑すぎる」(レイアウト自体はシンプル)ではなく、「単純なリストより複雑です」と言いました。私は全部を膨らませることに問題はないでしょう。問題は、リストの後ろにある要素(私の図のイメージ)を考慮して、私が「ListView」のヘッダーでレイアウトを動作させる方法がわからないことです。 'ListView'の上部に子要素の下に画像を付けることはできますか? – zeh

関連する問題