2014-12-15 3 views
6

Ich möchte eine ListView erstellen, wo jeder row zwei Tasten haben würde. Button1 und Button2.ListView mit Tasten und statische String Array

Ich habe ein paar Tutorials zum Erstellen von CustomAdapter oder zum Erweitern von BaseAdapter gelesen, aber keine von ihnen funktionierte in meinem Fall, deshalb eröffne ich hier eine neue Frage.

Ich habe eine statische (nicht verändern) String Array in meinem strings.xml:

<string-array name="locations_array"> 
    <item>Item1</item> 
    <item>Item2</item> 
</string-array> 

ich dieses Array in meinem Listview verwenden möchten (Ich führe ein normales Listview mit onClick Ereignis zu erstellen, aber jetzt will ich Hinzufügen von Schaltflächen zu jeder Zeile) und Hinzufügen von zwei Schaltflächen zu jeder Zeile, wo jeder sein eigenes onClick-Ereignis hat.

Ich habe Schritte von this answers here und einige andere Tutorials im Web gefolgt, aber ich bekomme immer NullPointerException beim Versuch, setText.

CustomAdapter.java:

public class CustomAdapter extends BaseAdapter implements ListAdapter { 
    private ArrayList<String> list = new ArrayList<>(); 
    private Context ctx; 

    public CustomAdapter(ArrayList<String> list, Context ctx){ 
     this.list = list; 
     this.ctx = ctx; 
    } 

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

    @Override 
    public Object getItem(int position) { 
     Log.d("TAG", list.get(position)); 
     return list.get(position); 
    } 

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

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View view = convertView; 
     if(view == null){ 
      LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      view = inflater.inflate(R.layout.layout_listview,null); 
     } 
     Log.d("TAG", list.get(position)); 
     TextView listItemText = (TextView) view.findViewById(R.id.list_item_string); 
     listItemText.setText(list.get(position)); 

     Button localData = (Button) view.findViewById(R.id.button1); 
     Button onlineData = (Button) view.findViewById(R.id.button2); 

     localData.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 

      } 
     }); 

     onlineData.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 

      } 
     }); 

     return view; 
    } 
} 

Und hier verwende ich den Adapter in meinem Fragment:

locationsArray = getResources().getStringArray(R.array.locations_array); 
ArrayList<String> data = new ArrayList<>(Arrays.asList(locationsArray)); 
CustomAdapter adapter = new CustomAdapter(data,getActivity()); 
listView.setAdapter(adapter); 

Aber das funktioniert nicht. Alle Tutorials konzentrieren sich auf etwas anderes als das, was ich brauche. Ich brauche einfach nur zwei Knöpfe in jeder Reihe, mit vorhandenem String Array. Ich möchte nichts dynamisch hinzufügen usw. Verwenden Sie einfach das String-Array, das ich bereits erstellt habe.

EDIT (Hinzufügen von XML-Dateien habe ich vergessen!)

R.layout.layout_listview (die EditText ist die Liste zu filtern):

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" android:layout_width="match_parent" 
    android:layout_height="match_parent"> 
    <EditText 
     android:id="@+id/et_filter" 
     android:layout_height="wrap_content" 
     android:layout_width="match_parent" 
     android:hint="Search Location"> 
    </EditText> 
    <ListView 
     android:id="@+id/list" 
     android:layout_height="wrap_content" 
     android:layout_width="match_parent"> 
    </ListView> 


</LinearLayout> 

R.layout.layout_listview_buttons:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <TextView 
     android:id="@+id/list_item_string" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerVertical="true" 
     android:layout_alignParentLeft="true" 
     android:paddingLeft="8dp" 
     android:textSize="18sp" 
     android:textStyle="bold" /> 

    <Button 
     android:id="@+id/button1" 
     android:layout_width="80dp" 
     android:layout_height="40dp" 
     android:layout_alignParentRight="true" 
     android:layout_alignParentTop="true" 
     android:focusable="false" 
     android:focusableInTouchMode="false" 
     android:text="Online Data" 

     android:textColor="#0099CC" /> 

    <Button 
     android:id="@+id/button2" 
     android:layout_width="80dp" 
     android:layout_height="40dp" 
     android:layout_alignParentRight="true" 
     android:layout_below="@+id/button1" 
     android:layout_marginTop="3dp" 
     android:focusable="false" 
     android:focusableInTouchMode="false" 
     android:text="Local Data" 
     android:textColor="#0099CC" /> 



</RelativeLayout> 

LogCat Ausnahme:

12-15 11:24:10.852 14626-14626/com.inodroid.myweatherapp E/AndroidRuntime﹕ FATAL EXCEPTION: main 
    Process: com.inodroid.myweatherapp, PID: 14626 
    java.lang.NullPointerException 
      at com.inodroid.myweatherapp.Data.CustomAdapter.getView(CustomAdapter.java:59) 

Zeile im Code:

listItemText.setText(list.get(position)); 

Hoffnung mir hier jemand helfen kann.

Prost

+0

Bitte fügen Sie Ihre R.layout.layout_listview Datei :-) – Kelevandos

+0

@ Kelevandos aah, sorry, weiß nicht, wie ich vergessen habe, XML-Dateien hinzuzufügen. Ich stelle beide auf! –

+0

Ich denke, dass der Stack-Trace auch nützlich sein wird – Lampapos

Antwort

1

Bitte versuchen Sie folgendes:

main.xml:

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

<ListView 
    android:id="@+id/lvItems" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 
</ListView> 

</LinearLayout> 

MainActivity.java:

public class MainActivity extends Activity { 

private ListView lvItems; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    lvItems = (ListView) findViewById(R.id.lvItems); 
    String[] locationsArray = getResources().getStringArray(
      R.array.locations_array); 
    CustomAdapter adapter = new CustomAdapter(this, locationsArray); 
    lvItems.setAdapter(adapter); 

lvItems.setOnItemClickListener(new OnItemClickListener() { 

     @Override 
     public void onItemClick(AdapterView<?> parent, View view, 
       int position, long id) { 
      ViewHolder holder = (ViewHolder) view.getTag(); 
      String item = holder.getItem(); 
      // Do what ever with your Item. 
      // If You need the position, you can take it from above 
      // position. 
     } 
    }); 
} 

} 

list_item.xml:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:orientation="vertical" 
android:padding="5dp" > 

<Button 
    android:id="@+id/btnLocalData" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="local Data" /> 

<TextView 
    android:id="@+id/tvItem" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_alignBottom="@+id/btnLocalData" 
    android:layout_alignTop="@+id/btnOnlineData" 
    android:layout_toLeftOf="@+id/btnOnlineData" 
    android:layout_toRightOf="@+id/btnLocalData" 
    android:gravity="center" 
    android:text="Item" 
    android:textSize="16dp" 
    android:textStyle="bold" /> 

<Button 
    android:id="@+id/btnOnlineData" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignParentRight="true" 
    android:text="Online Data" /> 

</RelativeLayout> 

CustomAdapter.java:

public class CustomAdapter extends ArrayAdapter<String> { 

private LayoutInflater lf; 

public CustomAdapter(Context context, String[] objects) { 
    super(context, 0, objects); 
    lf = LayoutInflater.from(context); 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    ViewHolder holder = null; 
    if (convertView == null) { 
     convertView = lf.inflate(R.layout.list_item, parent, false); 
     holder = new ViewHolder(); 
     holder.btnLocalData = (Button) convertView 
       .findViewById(R.id.btnLocalData); 
     holder.btnOnlineData = (Button) convertView 
       .findViewById(R.id.btnOnlineData); 
     holder.tvItem = (TextView) convertView.findViewById(R.id.tvItem); 
     holder.initListeners(); 
     convertView.setTag(holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    holder.setData(getItem(position)); 

    return convertView; 
} 

public static class ViewHolder { 
    TextView tvItem; 
    Button btnOnlineData; 
    Button btnLocalData; 
    String mItem; 

    public String getItem(){ 
     return mItem; 
    } 

    public void setData(String item) { 
     mItem = item; 
     tvItem.setText(item); 
    } 

    public void initListeners() { 
     btnLocalData.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       Toast.makeText(v.getContext(), 
         "Local Data Clicked : " + mItem, Toast.LENGTH_LONG) 
         .show(); 
      } 
     }); 
     btnOnlineData.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       Toast.makeText(v.getContext(), 
         "Online Data Clicked : " + mItem, Toast.LENGTH_LONG) 
         .show(); 
      } 
     }); 
    } 

} 

} 
+0

Dies ist eine großartige Antwort! :) Aber jetzt habe ich das Problem, dass onItemClick für ListView-Elemente nicht funktioniert. Nur Button-Klicks funktionieren. Aber ich möchte auch, dass Elemente aus ListView anklickbar sind und eigene onItemClickListeners haben, wie soll ich das mit meinem benutzerdefinierten Adapter implementieren? –

+0

Hey, ich bin es wieder. Kannst du vielleicht jetzt, wie bekomme ich die Position von ListView Item in der gleichen Zeile, auf die der Button geklickt wurde? Z.B. Wenn ich auf die Schaltfläche klicke, möchte ich den Text des ListView-Elements speichern, das sich in der gleichen Zeile wie die angeklickte Schaltfläche befindet. –

+0

@AndroidNFC Bitte sehen Sie meine aktualisierte Antwort –

1

Verwenden Sie bitte das ViewHolder-Muster. Sie benötigen diese:

item_listrow.xml:

<LinearLayout 
android:layout_height = "match_parent"; 
andorid:layout_width = "match_parent"; 
andorid:orientation = "horizontal"; 
> 

<Button 
android:id = "@+id/button1" 
android:layout_height = "match_parent"; 
andorid:layout_width = "0dp"; 
andorid:layout_weight = 1; 
/> 

<Button 
android:id = "@+id/button2" 
android:layout_height = "match_parent"; 
andorid:layout_width = "0dp"; 
andorid:layout_weight = 1; 
/> 

</LinaerLayout> 

Und Ihre Adapter getView() Methode sollte wie folgt aussehen:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    View view = convertView; 
    if(view == null){ 
     LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     view = inflater.inflate(R.layout.layout_listrow,null); 
     Holder h = new Holder(); 
     h.button1 = (Button) view.findViewById(R.id.button1); 
     h.button2 = (Button) view.findViewById(R.id.button2); 
     view.setTag(h);  
    } 

    Holder holder = (Holder) view.getTag(); 

    holder.button1.setText(list.get(0)); 
    holder.button2.setText(list.get(1)); 
    listItemText.setText(list.get(position)); 

    holder.button1.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 

     } 
    }); 

    holder.button2.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 

     } 
    }); 

    return view; 
} 

der Halter-Klasse verwendet oben: (nur Nest es im Inneren der Adapterklasse)

public static class Holder { 
    Button button1; 
    Button button2; 
} 

Hier ist der Code zum Verbergen der Tasten basierend auf einer gegebenen Methode isDeveloperMode():

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    View view = convertView; 
    if(view == null){ 
     LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     view = inflater.inflate(R.layout.layout_listrow,null); 
     Holder h = new Holder(); 
     h.button1 = (Button) view.findViewById(R.id.button1); 
     h.button2 = (Button) view.findViewById(R.id.button2); 
     view.setTag(h);  
    } 

    Holder holder = (Holder) view.getTag(); 

    if(isDeveloperMode()){ 
     holder.button1.setVisibility(View.VISIBLE); 
     holder.button2.setVisibility(View.VISIBLE); 
     holder.button1.setText(list.get(0)); 
     holder.button2.setText(list.get(1)); 
     listItemText.setText(list.get(position)); 

     holder.button1.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 

      } 
     }); 

     holder.button2.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 

      } 
     }); 
    } else { 
     holder.button1.setVisibility(View.GONE); 
     holder.button2.setVisibility(View.GONE); 
    } 

    return view; 
} 
+0

Der Code wurde von Hand eingegeben, also bitte entschuldigen Sie etwaige Fehler oder Tippfehler ;-) – Kelevandos

+0

Ich habe XMLs hinzugefügt, wo die Schaltflächen deklariert sind. Aber ich habe die Holder-Klasse nicht benutzt, das stimmt, ich werde versuchen, das hinzuzufügen. Allerdings bekomme ich einen LogCat-Fehler "NullPointerException" auf meinem 'setText (list.get (Position)' –

+0

Bitte implementieren Sie den Code und versuchen Sie es erneut. – Kelevandos

0

Ihren Code die in Adapter

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    if(convertView== null){ 
     LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     convertView= inflater.inflate(R.layout.layout_listview,null); 
    } 
    Log.d("TAG", list.get(position)); 
    TextView listItemText = (TextView) convertView.findViewById(R.id.list_item_string); 
    listItemText.setText(list.get(position)); 

    Button localData = (Button) convertView.findViewById(R.id.button1); 
    Button onlineData = (Button) convertView.findViewById(R.id.button2); 

    localData.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 

     } 
    }); 

    onlineData.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 

     } 
    }); 

    return convertView; 
} 
0

statt

Versuchen Sie folgende Änderung
@Override 
public View getView(int position, View convertView, ViewGroup parent) {  
      View view = convertView; 
      if(view == null){ 
       LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
       view = inflater.inflate(R.layout.layout_listview,null); 
      } 
      Log.d("TAG", list.get(position)); 
      TextView listItemText = (TextView) view.findViewById(R.id.list_item_string); 

Verwendung

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
      View view = super.getView(position, convertView, parent);  
      Log.d("TAG", list.get(position)); 
      TextView listItemText = (TextView) view.findViewById(R.id.list_item_string);