2012-10-08 8 views
11

Jak widziałem na wcześniej zadanych pytaniach, w klasie niestandardowych adapterów (np. MyAdapter rozszerza ArrayAdapter) zawsze używają zawężonego układu listy elementów XML . Co mam nadzieję zrobić, to stworzyć wszystko zupełnie nie używając Java i XML ...Tworzenie listView z niestandardowymi elementami listy programowo w systemie Android - brak elementu listy elementów XML

// for example 
String[] wordlist = new String[] {a, b, c}; 

LinearLayout list_item_layout = new LinearLayout(this); 
list_item_layout.setId(5000); 

TextView listText = new TextView(this); 
listText.setId(5001); 

listLayout.addView(listText); 

ListView list = new ListView(this); 

// ** QUESTION ** do I declare a programmatic .setAdapter() like this? 
// ** TAKE NOTE ** I passed 'wordlist' here.. 
list.setAdapter(new MyAdapter(this, list_item_layout.getId(), listText.getId(), wordlist)); 

a następnie przez MyAdapter ...

private class MyAdapter extends ArrayAdapter<String> { 

    public MyAdapter(Context context, int resource, int textViewResourceId, String[] strings) { 
     super(context, resource, textViewResourceId, strings); 
    } 

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

     View v = convertView; //is this the list_item_layout that I passed?? 
     TextView tv = (TextView) v.findViewById(5001); 

     // ** QUESTION ** do I pass 'wordlist' again here? 
     tv.setText(wordlist[position]); 

     return v; 
    } 
} 

Co się dzieje, gdy uruchomię to na moim urządzeniu jest ja uzyskać następujące błędy ...

10-08 23:11:19.775: E/AndroidRuntime(18276): FATAL EXCEPTION: main 
    10-08 23:11:19.775: E/AndroidRuntime(18276): android.content.res.Resources$NotFoundException: String resource ID #0x0 
    10-08 23:11:19.775: E/AndroidRuntime(18276): at android.content.res.Resources.getText(Resources.java:222) 
    10-08 23:11:19.775: E/AndroidRuntime(18276): at android.widget.TextView.setText(TextView.java:3011) 
    10-08 23:11:19.775: E/AndroidRuntime(18276): at com.turista.client.TuristaClientMain.onClick(TuristaClientMain.java:113) 
    10-08 23:11:19.775: E/AndroidRuntime(18276): at android.view.View.performClick(View.java:2538) 
    10-08 23:11:19.775: E/AndroidRuntime(18276): at android.view.View$PerformClick.run(View.java:9152) 
    10-08 23:11:19.775: E/AndroidRuntime(18276): at android.os.Handler.handleCallback(Handler.java:587) 
    10-08 23:11:19.775: E/AndroidRuntime(18276): at android.os.Handler.dispatchMessage(Handler.java:92) 
    10-08 23:11:19.775: E/AndroidRuntime(18276): at android.os.Looper.loop(Looper.java:123) 
    10-08 23:11:19.775: E/AndroidRuntime(18276): at android.app.ActivityThread.main(ActivityThread.java:3691) 
    10-08 23:11:19.775: E/AndroidRuntime(18276): at java.lang.reflect.Method.invokeNative(Native Method) 
    10-08 23:11:19.775: E/AndroidRuntime(18276): at java.lang.reflect.Method.invoke(Method.java:507) 
    10-08 23:11:19.775: E/AndroidRuntime(18276): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847) 
    10-08 23:11:19.775: E/AndroidRuntime(18276): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605) 
    10-08 23:11:19.775: E/AndroidRuntime(18276): at dalvik.system.NativeStart.main(Native Method) 

Czy ktoś może wyjaśnić, jak to zrobić programowo?


* EDITED * 09 października 2012


Ok, a ja wciąż tkwi w tej kwestii myślę Zrobiłem kilka ulepszeń, ale wciąż pojawiają się komunikaty o błędach. Ulepszony kod jest następująca ..

//wordlist is a global variable 
String[] wordlist = new String[] {a, b, c}; 

// .. 
// .. inside onCreate... 

ListView list = new ListView(this); 
     list.setAdapter(new MyAdapter(this, R.layout.listitem, R.id.mLargeTextView, wordlist)); 
// since the ArrayAdapter class needs XML parameters to inflate, I created a dummy layout 

teraz wewnątrz klasy MyAdapter ..

private class MyAdapter extends ArrayAdapter<String> { 

    public MyAdapter(Context context, int resource, int textViewResourceId, String[] strings) { 
     super(context, resource, textViewResourceId, strings); 
    } 

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


     LinearLayout listLayout = new LinearLayout(Main.this); 
     listLayout.setLayoutParams(new LayoutParams(wrapContent, wrapContent)); 
     listLayout.setId(5000); 

     TextView listText = new TextView(Main.this); 
     listText.setId(5001); 

     listLayout.addView(listText); 

     listText.setText(wordlist[position]); 

     return listLayout; 
    } 
} 

Jak widać, myślę, że trzeba zastąpić getView aby wyświetlić mój własny pogląd, więc jest to co ja zrobiłem. Niestety, myślę, że źle to zrozumiałem. Oto błędy ..

10-09 09:24:10.095: E/AndroidRuntime(2517): FATAL EXCEPTION: main 
    10-09 09:24:10.095: E/AndroidRuntime(2517): java.lang.ClassCastException: android.view.ViewGroup$LayoutParams 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.widget.ListView.measureScrapChild(ListView.java:1183) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.widget.ListView.measureHeightOfChildren(ListView.java:1266) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.widget.ListView.onMeasure(ListView.java:1175) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.view.View.measure(View.java:8366) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.widget.FrameLayout.onMeasure(FrameLayout.java:250) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.view.View.measure(View.java:8366) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.widget.FrameLayout.onMeasure(FrameLayout.java:250) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.view.View.measure(View.java:8366) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1017) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.widget.LinearLayout.measureVertical(LinearLayout.java:386) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.widget.LinearLayout.onMeasure(LinearLayout.java:309) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at com.android.internal.widget.WeightedLinearLayout.onMeasure(WeightedLinearLayout.java:60) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.view.View.measure(View.java:8366) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.widget.FrameLayout.onMeasure(FrameLayout.java:250) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.view.View.measure(View.java:8366) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.widget.FrameLayout.onMeasure(FrameLayout.java:250) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.view.View.measure(View.java:8366) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.view.ViewRoot.performTraversals(ViewRoot.java:847) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1868) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.os.Handler.dispatchMessage(Handler.java:99) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.os.Looper.loop(Looper.java:123) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at android.app.ActivityThread.main(ActivityThread.java:3691) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at java.lang.reflect.Method.invokeNative(Native Method) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at java.lang.reflect.Method.invoke(Method.java:507) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605) 
    10-09 09:24:10.095: E/AndroidRuntime(2517):  at dalvik.system.NativeStart.main(Native Method) 
+0

Czy mogę zapytać, dlaczego chcesz to zrobić programową styl zamiast za pomocą XML? – Zerkz

+0

już ustawiłeś identyfikator, dlaczego znajdujesz nowy TextView z tym identyfikatorem? użyj tv.getID(). –

+0

@Kumar co masz na myśli? Użyłem v.findViewById (5001). – daryl

Odpowiedz

21

ListView rozciąga AbsListView która z kolei rozciąga AdapterView która rozciąga się widok grupy. Więc całe dziecko ListView zostanie dodane do ViewGroup. Aby ustawić parametr układu, można użyć ViewGroup.LayoutParam podczas ustawiania parametru układu dla listLayout.

Lub spróbuj AbsListView.LayoutParams do ustawiania układu param dla listLayout

Spróbuj go i daj mi znać, czy to zadziałało.

następujący kod działa poprawnie ..

public class MainActivity1 extends Activity { 

    String[] wordlist = new String[] { "a", "b", "c" }; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     ListView list = new ListView(this); 
     list.setAdapter(new MyAdapter(this, wordlist)); 

     setContentView(list); 
    } 

    private class MyAdapter extends ArrayAdapter<String> { 

     public MyAdapter(Context context, String[] strings) { 
      super(context, -1, -1, strings); 
     } 

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

      LinearLayout listLayout = new LinearLayout(MainActivity1.this); 
      listLayout.setLayoutParams(new AbsListView.LayoutParams(
        AbsListView.LayoutParams.WRAP_CONTENT, 
        AbsListView.LayoutParams.WRAP_CONTENT)); 
      listLayout.setId(5000); 

      TextView listText = new TextView(MainActivity1.this); 
      listText.setId(5001); 

      listLayout.addView(listText); 

     listText.setText(super.getItem(position)); 

      return listLayout; 
     } 
    } 
} 

Problem polegał na tym, że domyślnie Eclipse importu ViewGroup.LayoutParams które są niezgodne z AbsListView.LayoutParams które muszą być stosowane do ustawiania układu param do widzenia wrócił z metody getView().

proszę sprawdzić i dać mi znać jak poszło ..

+0

Właśnie przetestowałem to z AbsListView.LayoutParams i działa dobrze. Zaktualizowałem moją odpowiedź odpowiednio. –

+0

Wow to działa. Nie wiedziałem, że w ramach tej metody getView() LayoutParams jest obsługiwany inaczej, a poleganie w dużej mierze na automatycznym importowaniu dokonanym przez Eclipse nie jest dobrą rzeczą. – daryl

+0

Dzięki. Prawie zrezygnowałem z tego pomysłu, aby wszystko zrobić programowo. Ostatnie pytanie, widzę, że przekazałeś tablicę "listy słów" w setAdapter (nowy MyAdapter()) wewnątrz onCreate. To znaczy, że musi już być gdzieś w MyAdapter ... Jeśli "lista słów" nie jest zadeklarowana globalnie, jak ją nazwiesz? Ponownie dziękuję Praful. Całkowicie go przybiłeś. – daryl

2

Aby dodać do powyższej odpowiedzi, ustawienie identyfikatora przy stałej liczbie nie jest dobrym pomysłem.

Zamień listLayout.setId(5000); z, listLayout.setId(View.generateViewId());

W przypadku, gdy są kierowane API 16 i poniżej, patrz this.

Powiązane problemy