2016-04-15 13 views
0

In einem horizontalen LinearLayout (die Bildschirmbreite entspricht), habe ich zwei ListView-Instanzen (mit dynamischen Listenelementen) und eine TextView dazwischen. Mit dem TextView als Canvas möchte ich (Bezier) Linien zeichnen, die entweder das ausgewählte Listenelement im linken ListView mit allen Listenelementen im rechten ListView verbinden oder umgekehrt. Nun ist es durchaus möglich, dass entweder das ausgewählte Listenelement oder irgendeines der Listenelemente auf der anderen Seite außerhalb des sichtbaren Bereichs des ListViews liegt. In diesem Fall würde ich diese Linien (von oben/unten kommend oder oben/unten) nur so weit zeichnen, wie sie sichtbar sind. Um diese Linien zu zeichnen, brauche ich am Anfang und am Ende jeder Linie x- und y-Werte. x ist nur textView.getLeft() und textView.getRight(), aber y hängt von der aktuellen Bildlaufposition der beiden Listen ab.How to getY() für ListView-Elemente

Mein Problem ist es, die aktuellen y-Werte für bestimmte Listview-Elemente zu erhalten:

list.getChildAt(indexOfCurrentlySelectedItem).getY() 

ich diese Werte zugreifen müssen, sobald die Liste geführt gelegt hat. Ich muss bestimmen, welche Listenelemente und welche Listenelemente nicht sichtbar sind. (Haben die nicht sichtbaren Listenelemente einen y-Wert? Eine Ansicht? Eine wiederverwendbare Ansicht (unter Verwendung des Haltermusters)?). Ich muss in der Lage sein, eine Liste zu durchlaufen, die ich bestelle, um diese y-Werte an meine onDraw-Methode der TextView zu übergeben. Und schließlich muss ich einen Mechanismus installieren, um die Zeilen nach dem Scrollen neu zu zeichnen.

Wie bekomme ich die aktuellen y-Werte (nach dem Layout und nach dem Scrollen)? Muss ich die sichtbaren Positionen in einem OnScrollListener verfolgen? Muss ich in einem OnGlobalLayoutListener auf das Ende des Listenlayouts warten? Muss ich (auch) für jedes Listenelement auf das Ende des Layouts der Listenelemente in einem OnGlobalLayoutListener achten?

Antwort

0

Okay, ich habe eine gute Lösung gefunden: Der OnScrollListener bietet alles, was ich brauche, während der OnGlobalLayoutListener hier nicht benötigt wird.

public class ArrayListAdapter extends ArrayAdapter<String> 
    implements AbsListView.OnScrollListener 

... 

@Override 
public void onScrollStateChanged(AbsListView view, int scrollState) {} 

@Override 
public synchronized void onScroll(final AbsListView listView, int firstVisibleItem, 
            int visibleItemCount, int totalItemCount) { 
    List<Integer>yList = new ArrayList<>(); 
    int checkedPosition = listView.getCheckedItemPosition(); 
    double yChecked = 0; 

    for (int pos = 0; pos < totalItemCount; pos++) { 
     CheckedTextView tv = (CheckedTextView) this 
       .getViewByPosition(pos, listView, firstVisibleItem, 
         firstVisibleItem + visibleItemCount - 1); 
     if (pos == checkedPosition) { 
      yChecked = tv.getY(); 
     } 
     yList.add(pos, tv.getY()); 
    }   
    // Here I pass the fresh y-values to the fragment holding the 
    // two ListViews. After some further calculations the fragment 
    // passes the data to the TextView where it is stored and 
    // this.invalidate is called to eventually trigger the onDraw method. 
    originalFragment.setScrollData(yList, yChecked); 
} 

private View getViewByPosition(int pos, AbsListView listView, int firstVisibleItem, 
           int lastVisibleItem) { 
    if (pos < firstVisibleItem || pos > lastVisibleItem) { 
     // The next line is the only downside of this solution I have 
     // found so far. If the convertView of the getView(int 
     // position, View convertView, ViewGroup parent) method is null 
     // the holder pattern I applied in my adapter becomes useless. 
     // In my case the recreation of the CheckedTextViews is fast 
     // enough though. 
     return listView.getAdapter().getView(pos, null, listView); 
    } else { 
     return listView.getChildAt(pos - firstVisibleItem); 
    } 
}