2013-08-30 11 views
9

Mam ListView, który zajmuje cały ekran, ale czasami nie ma w nim wystarczającej ilości elementów, aby całkowicie pokryć widget ListView. Chciałbym móc odpowiadać na kliknięcia na tym pustym polu poniżej ostatniego elementu, który w rzeczywistości nie zawiera elementu (co oznacza, że ​​setOnItemClickListener nie jest właściwe).Jak można odsłuchiwać zdarzenia kliknięcia w ListView, które występują poza elementami listy?

Próbowałem setOnClickListener (które wyłączają dla samego siebie ListView) w widoku nadrzędnym, ale wydaje się, że kliknięcia nie docierają do niego. Próbowałem też setOnTouchListener na ListView, ale to spowodowało, że niektóre kliknięcia przedmiotów nie zostały zarejestrowane z jakiegoś powodu. Wszelkie pomysły, jak to osiągnąć?

+3

FWIW, złożony problem, aby uzyskać 'setOnClickListener()' ograniczenie zniesione, jak ty zrób doskonały punkt: http://code.google.com/p/android/issues/detail?id=59559 – CommonsWare

Odpowiedz

0

Jednym z możliwych sposobów osiągnięcia tego jest ustawienie listView na height="wrap_content" Jeśli to zrobisz, możesz zastąpić onTouchEvent() dla swojej aktywności, aby uzyskać zdarzenia od momentu dotknięcia przez użytkownika pustego miejsca.

layout.xml

<ListView 
    android:id="@+id/list" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:entries="@array/list" /> 

Activity.java

public class MainActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     ListView mList = (ListView)findViewById(R.id.list); 
     mList.setOnItemClickListener(new OnItemClickListener() { 
      @Override 
      public void onItemClick(AdapterView<?> parent, View v, int pos,long id) { 
       Toast.makeText(v.getContext(), ""+pos, Toast.LENGTH_SHORT).show(); 
      } 
     }); 
    } 
    @Override 
    public boolean onTouchEvent(MotionEvent me){ 
     if(me.getAction() == MotionEvent.ACTION_DOWN){ 
      Toast.makeText(this, "Empty space", Toast.LENGTH_SHORT).show(); 
      return true; 
     } 
     return false; 
    } 
} 

Jednak jeśli liczą na wysokości ListView będącego match_parent z jakiegoś powodu (np tło odkształcalne), to won nie będzie idealnym rozwiązaniem.

+0

Czy próbowałeś tego, czy wiesz od ręki, czy ListView dobrze współpracuje z wrap_content? To właśnie uderza w moją intuicję jako coś, co nie byłoby dobrze traktowane: czy nie spróbuje zmierzyć wszystkich dzieci ListView? – Foxichu

+0

Spróbowałem. Zabrakło emulatora i wydawało się, że działa dobrze. – FoamyGuy

0

Umieść pusty linearlayout poniżej pogrupowanych poprzez ustawienie odpowiedniej wysokości do ListView. Umieść metodę onClick() na tym układzie liniowym. To musi to zrobić.

5

Zrobiłem podobny problem, gdy potrzebowałem zamknąć rozwinięte elementy listy po kliknięciu pustego miejsca. Oto jak to rozwiązałem.

public class CustomListView extends ListView { 

    private OnNoItemClickListener mOnNoItemClickListener; 

    public interface OnNoItemClickListener { 
    void onNoItemClicked(); 
    } 

    public CustomListView(Context context) { 
    super(context); 
 } 

    public CustomListView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    } 

    public CustomListView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    } 

    @Override 
    public boolean dispatchTouchEvent(MotionEvent ev) { 
    //check whether the touch hit any elements INCLUDING ListView footer 
    if(pointToPosition((int) (ev.getX() * ev.getXPrecision()), 
     (int) (ev.getY() * ev.getYPrecision())) == -1 && ev.getAction() == MotionEvent.ACTION_DOWN) { 
     if(mOnNoItemClickListener != null) { 
     mOnNoItemClickListener.onNoItemClicked(); 
     } 
    } 
    return super.dispatchTouchEvent(ev); 
    } 

    public void setOnNoItemClickListener(OnNoItemClickListener listener) { 
    mOnNoItemClickListener = listener; 
    } 

} 

Następnie użyć tego CustomListView w pliku XML, zamiast zwykłej ListView i wdrożenie OnNoItemClickListener wewnątrz swojej działalności/fragmentu i nazywają mListView.setOnNoItemClickListener (this); w onCreate, aby włączyć funkcję oddzwaniania do funkcji onNoItemClicked().

Należy zauważyć, że jeśli Twój ListView ma nagłówki lub stopki, są one traktowane jako elementy listy, a funkcja onNoItemClicked() nie będzie wywoływana.

0

Łączenie niektórych innych odpowiedzi, wpadłem na to, że działa dobrze dla mojego użytku przypadku

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    ... setup list view and other view state 
    listView.setOnTouchListener(new View.OnTouchListener() { 
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     if (event.getAction() == MotionEvent.ACTION_DOWN && 
      listView.pointToPosition((int) (event.getX() * event.getXPrecision()), (int) (event.getY() * event.getYPrecision())) == -1) { 
     collapseExpandedListItem(); 
     return true; 
     } 
     return false; 
    } 
    }); 
} 
Powiązane problemy