2016-08-19 2 views
0

Новинка для Android и Java и обучения, но мне кажется, что у вас нет чего-то фундаментального для обнаружения щелчков элементов в ListView.Исключение Null Pointer при вызове setOnItemClickListener

У меня есть активность, которая представляет собой пару кнопок со списком под ними. Каждый элемент ListView имеет значок, на который можно щелкнуть, что в конечном итоге перейдет к другому действию и отметке времени (в настоящее время просто указывается, что клик работал через Toast). Обнаружение нажатия на значок работает, но я пытаюсь реализовать выбор элементов в ListView, и именно там я столкнулся с проблемой.

Я просмотрел множество примеров, таких как this, и я думаю, что я делаю это, как предписано, но я, очевидно, что-то отсутствует, так как я получаю исключение во время выполнения «java.lang.NullPointerException: попытка вызвать виртуальный метод«недействительным android.widget.ListView.setOnItemClickListener (android.widget.AdapterView $ OnItemClickListener)»на нулевой ссылке на объект:»

Вот макет для просмотра:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context="com.example.foo.magma.ViewPassagesActivity"> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:id="@+id/linearLayout"> 
     <Button 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="Update" 
      android:onClick="update" 
      android:id="@+id/updateButton" 
      android:layout_alignParentTop="true" 
      android:layout_alignParentLeft="true" 
      android:layout_alignParentStart="true" 
      android:layout_weight="1"/> 

     <Button 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="Delete" 
      android:onClick="delete" 
      android:id="@+id/deleteButton" 
      android:layout_alignParentTop="true" 
      android:layout_alignParentRight="true" 
      android:layout_alignParentEnd="true" 
      android:layout_weight="1"/> 
    </LinearLayout> 

    <ListView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/passagesListView" 
     android:layout_alignParentBottom="true" 
     android:layout_centerHorizontal="true" 
     android:layout_below="@+id/linearLayout" /> 
    </RelativeLayout> 

Вот макет для в ListView. Как уже упоминалось, это значок слева с временной меткой:

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

    <ImageView 
     android:id="@+id/icon" 
     android:layout_width="50dp" 
     android:layout_height="50dp" 
     android:layout_marginLeft="4dp" 
     android:layout_marginRight="10dp" 
     android:layout_marginTop="4dp" 
     android:src="@drawable/curve" > 
    </ImageView> 

    <TextView 
     android:id="@+id/label" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Timestamp: " 
     android:textStyle="bold" 
     android:textSize="20dp" 
     android:layout_centerVertical="true" 
     android:layout_toRightOf="@+id/icon" 
     android:layout_toEndOf="@+id/icon"> 
     android:layout_toRightOf="@+id/icon" 
    </TextView> 

    <TextView 
     android:id="@+id/time" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="layouttesttime" 
     android:textSize="20dp" 
     android:layout_below="@+id/date" 
     android:layout_alignRight="@+id/date" 
     android:layout_alignEnd="@+id/date" 
     android:layout_alignLeft="@+id/date" 
     android:layout_alignStart="@+id/date"> 
    </TextView> 

    <TextView 
     android:id="@+id/date" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_marginLeft="10dp" 
     android:text="layouttestdate" 
     android:textSize="20dp" 
     android:layout_alignTop="@+id/icon" 
     android:layout_alignParentRight="true" 
     android:layout_alignParentEnd="true" 
     android:layout_toRightOf="@+id/label" 
     android:layout_toEndOf="@+id/label"> 
    </TextView> 
    </RelativeLayout> 

Вот он OnCreate() от моей деятельности, который устанавливает мой адаптер:

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

    ListView passagesListView = (ListView) findViewById(R.id.passagesListView); 
    assert passagesListView != null; 

    buildPassageList(); 

    PassagesViewAdapter adapter = new PassagesViewAdapter(this, R.layout.passages_row_layout, passages); 
    passagesListView.setAdapter(adapter); 


} 

А вот где я, имеющий вопрос. Работает OnClickListener для значка. Я намерен обнаружить выбор элемента ListView, чтобы его можно было удалить. Однако, когда я добавляю вызов setOnItemClickListener(), я получаю исключение во время выполнения.

import android.content.Context; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.AdapterView; 
import android.widget.ArrayAdapter; 
import android.widget.ImageView; 
import android.widget.ListView; 
import android.widget.TextView; 
import android.widget.Toast; 

import java.util.List; 


public class PassagesViewAdapter extends ArrayAdapter<Passage>{ 

    private int resource; 
    private List<Passage> passages; 

    public PassagesViewAdapter(Context context, int resource, List<Passage> passages) { 
     super(context, resource, passages); 
     this.resource = resource; 
     this.passages = passages; 
    } 

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

     View view = convertView; 

     if (view == null) { 
      LayoutInflater li = LayoutInflater.from(getContext()); 
      view = li.inflate(resource, null); 
     } 

     Passage passage = this.passages.get(position); 

     TextView time = (TextView) view.findViewById(R.id.time); 
     TextView date = (TextView) view.findViewById(R.id.date); 
     ImageView icon = (ImageView) view.findViewById(R.id.icon); 
     icon.setTag(new Integer(position)); 
     final String positionStr = icon.getTag().toString(); 

     // This works great! 
     icon.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Toast.makeText(getContext(), "You clicked on " + positionStr, Toast.LENGTH_SHORT).show(); 
      } 
     }); 

     ListView passagesListView = (ListView) view.findViewById(R.id.passagesListView); 
     assert passagesListView != null; 

     // ** This call results in a runtime error for null pointer reference. 
     passagesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
      @Override 
      public void onItemClick(AdapterView<?> adapter, View view, int position,long arg3) { 
       Toast.makeText(getContext(), "Foo", Toast.LENGTH_SHORT).show(); 
      } 
     }); 

     time.setText(passage.getPassageTime()); 
     date.setText(passage.getPassageDate()); 

     return view; 
    } 

} 

ответ

1

Это потому, что View у вас есть в вашем адаптере представляет View вы видите в списке, а не макет вашего ViewPassagesActivity. У вас нет ListView в ваших ListView элементах, чтобы его не найти, и findViewById возвращает null. Если переместить часть, где вы установили OnItemClickListener к onCreate вашего ViewPassagesActivity, все должно работать штраф

Удалить эту часть от адаптера

// ** This call results in a runtime error for null pointer reference. 
passagesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
    @Override 
    public void onItemClick(AdapterView<?> adapter, View view, int position,long arg3) { 
     Toast.makeText(getContext(), "Foo", Toast.LENGTH_SHORT).show(); 
    } 
}); 

и добавить его в OnCreate вашей деятельности в этом, как

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

    ListView passagesListView = (ListView) findViewById(R.id.passagesListView); 
    assert passagesListView != null; 

    buildPassageList(); 

    PassagesViewAdapter adapter = new PassagesViewAdapter(this, R.layout.passages_row_layout, passages); 
    passagesListView.setAdapter(adapter); 

    // ** This call results in a runtime error for null pointer reference. 
    passagesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
     @Override 
     public void onItemClick(AdapterView<?> adapter, View view, int position,long arg3) { 
      Toast.makeText(getContext(), "Foo", Toast.LENGTH_SHORT).show(); 
     } 
    }); 
} 
+0

Aha. Я понял. Спасибо за быстрый ответ. Переместился на OnCreate(). – sje

0

Попробуйте расширить свой адаптер от BaseAdapter.

Это

public class PassagesViewAdapter extends ArrayAdapter<Passage>{ 

к этому

public class PassagesViewAdapter extends BaseAdapter { 

Также ваш setOnItemClickListener должен быть в OnCreate функции в вашей деятельности, а не в адаптере.

Смежные вопросы