webentwicklung-frage-antwort-db.com.de

Android ScrollView beginnt nicht oben, sondern am Anfang der GridView

Ich habe ein Problem mit einem ScrollView, in dem sich ein personalisiertes GridView und andere Ansichten befinden. Beim ersten Start der Aktivität beginnt das ScrollView an der Spitze, aber wenn ich die Activity zu anderen Zeitpunkten besuche, beginnt das ScrollView am Anfang von GridView.I verwendete die Klasse ExpandableHeightGridView in this link für meine GridView . Der XML-Code für das Activity-Layout ist der folgende:

<ScrollView xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/scrollViewLuogo"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="#fff" >

<RelativeLayout
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="#fff" >

    <LinearLayout
        Android:id="@+id/linearLayout2"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content" >

        <ImageView
            Android:id="@+id/imageView1"
            Android:layout_width="150dp"
            Android:layout_height="100dp"
            Android:layout_marginLeft="14dp"
            Android:layout_marginRight="10dp"
            Android:layout_marginTop="10dp"
            Android:adjustViewBounds="true"
            Android:maxHeight="200dp"
            Android:maxWidth="200dp"
            Android:scaleType="fitXY"
            Android:src="@Android:drawable/ic_menu_gallery" />

        <LinearLayout
            Android:id="@+id/linearLayout1"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_marginTop="10dp"
            Android:orientation="vertical" >

            <TextView
                Android:id="@+id/nomeTVActivityLuogo"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:textStyle="bold"
                Android:textSize="17sp"
                Android:textColor="#005788" />

            <TextView
                Android:id="@+id/indirizzoTVActivityLuogo"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content" />
        </LinearLayout>
    </LinearLayout>

    <LinearLayout
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_below="@+id/linearLayout2"
        Android:layout_marginTop="10dp"
        Android:orientation="vertical" >

        <ImageView
            Android:id="@+id/imageViewMappaLuogo"
            Android:layout_width="wrap_content"
            Android:layout_height="60dp"
            Android:layout_marginBottom="10dp"
            Android:layout_marginLeft="14dp"
            Android:layout_marginRight="14dp"
            Android:layout_marginTop="5dp"
            Android:scaleType="fitXY"
            Android:src="@drawable/sfondo_mappa" />

        <TextView
            Android:id="@+id/textView1"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_marginLeft="14dp"
            Android:text="Immagini"
            Android:textColor="#97d6f9" />

        <View
            Android:layout_width="fill_parent"
            Android:layout_height="2dp"
            Android:layout_marginLeft="14dp"
            Android:layout_marginRight="14dp"
            Android:layout_marginTop="5dp"
            Android:background="#97d6f9" />

        <com.example.mappine.ExpandableHeightGridView
            Android:id="@+id/gridViewLuogo"
            Android:layout_width="wrap_content"
            Android:layout_height="match_parent"
            Android:layout_marginBottom="10dp"
            Android:layout_marginLeft="10dp"
            Android:layout_marginRight="10dp"
            Android:layout_marginTop="10dp"
            Android:numColumns="3" >
        </com.example.mappine.ExpandableHeightGridView>

    </LinearLayout>

</RelativeLayout>

Ich habe versucht, den Code scrollView.fullScroll(ScrollView.FOCUS_UP); zu verwenden, aber er hat nicht funktioniert. Und selbst mit scrollView.scrollTo(0, 0); hatte ich keinen Erfolg. Der einzige Code, der funktionierte, war:

    scrollView.post(new Runnable() 
      { 
         public void run() { 
             scrollViewLuogo.fullScroll(ScrollView.FOCUS_UP); 
         } 
      });

aber es macht eine schnelle Animation vom oberen Rand des GridView bis zum oberen Rand des Bildschirms und ich mag es nicht.

Irgendein Vorschlag??

50
user2328149

Lösung:

Ok, Entschuldigung, wenn es sich um eine verspätete Antwort handelt, aber ich bin über das gleiche Problem gestolpert (nur, dass ich stattdessen ListView verwendet habe) und mit ein wenig Versuch und Irrtum ich habe die Lösung gefunden dazu:

Grundsätzlich besteht das Problem darin, dass das untergeordnete GridView/ListView-Objekt automatisch den übergeordneten Fokus (ScrollView) anfordert, wenn Sie den Inhalt mit ExpandableHeightGridView "hacken" und dessen Größe ändern. Dies geschieht, nachdem das Layout gerendert wurde. Daher wird diese Animation angezeigt, wenn Es wird versucht, mit scrollTo () nach oben zu scrollen (geschieht, nachdem das Layout erstellt wurde und die Größe des Rasters geändert wurde, sodass der generische Rückruf nutzlos ist, um dies programmgesteuert zu behandeln).

Die einfachste Lösung, die ich gefunden habe, war also einfach, die fokussierbare Eigenschaft in der ListView/GridView zu deaktivieren:

listView.setFocusable(false);

Wenn Sie die Aktivität zum ersten Mal eingeben, wird der Fokus standardmäßig verwendet und hängt nicht von Listview/GridView ab.

Und alles funktioniert gut =)

161

Am einfachsten können Sie in der übergeordneten ScrollView die folgenden XML-Attribute hinzufügen:

Android:descendantFocusability="beforeDescendants"
Android:focusableInTouchMode="true"

Das bedeutet, dass die ScrollView als Ganzes diejenige ist, die beim Starten der Aktivität den Fokus anstelle eines inneren Containers erhält. Dies ist z. B. auch nützlich, wenn Sie einen Text innerhalb des Layouts bearbeiten und nicht möchten, dass der Fokus sofort angezeigt wird und die Tastatur beim Aufrufen eines Bildschirms angezeigt wird (dasselbe Prinzip).

Ihre ScrollView auf Ihrem Layout würde also so aussehen:

<ScrollView xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/scrollViewLuogo"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:descendantFocusability="beforeDescendants"
    Android:focusableInTouchMode="true"
    Android:background="#fff" >
21
Disruption

Fügen Sie diese zwei Zeilen einfach in Ihr übergeordnetes Layout ein

Android: focusable = "true" Android: focusableInTouchMode = "true"

Versuchen Sie dies, ich hoffe, es wird für Sie funktionieren

Wenn Sie programmgesteuert nach oben/unten scrollen möchten, können Sie dies tun (von hier ):

Für den Fokus nach unten:

((ScrollView) findViewById(R.id.scrollView)).post(new Runnable() { 
    public void run() { 
        ((ScrollView) findViewById(R.id.scrollView)).fullScroll(View.FOCUS_DOWN); 
    } 
});

Für den Fokus nach oben

((ScrollView) findViewById(R.id.scrollView)).post(new Runnable() { 
    public void run() { 
        ((ScrollView) findViewById(R.id.scrollView)).fullScroll(View.FOCUS_UP); 
    } 
});
3
Piasy

Fügen Sie diese Codezeile einfach in das Child of ScrollView ein

Android:focusableInTouchMode="true"
3
Bilal Ahmad

ScrollView 

Android:fitsSystemWindows="false"
3
Matheus Marques

Leider ist das Beispiel, dem Sie gefolgt sind, extrem schlecht. ListViews und GridViews sollten niemals in ScrollViews eingefügt werden.

Der Zweck von ScrollView besteht darin, der untergeordneten Ansicht eine unendliche Höhe zu geben. Der Zweck von List/GridView besteht darin, einen möglicherweise sehr großen Datensatz zu übernehmen und nur genügend Elementansichten zu generieren, um den Platz zu füllen, der ihm gleichzeitig zur Verfügung steht, um die Effizienz zu erhöhen. Beide sind in der Lage, ihren Inhalt ohne den anderen zu scrollen.

Wenn Sie eine List/GridView in eine ScrollView einfügen, heißt es: "Unaufhaltsame Kraft, unbewegliches Objekt treffen". Entweder haben Sie den Punkt von List/GridView besiegt, oder Sie haben den Punkt von ScrollView besiegt, indem Sie sie kombinieren.

Bessere Möglichkeiten, andere Inhalte in den gleichen Bildlaufbereich aufzunehmen, umfassen die Verwendung von Kopf-/Fußzeilenansichten mit einer ListView oder das Zusammenfügen des Inhalts von Listenadaptern auf andere Weise in einem einzigen Adapter. Das Erstellen von ListView-Elementen mit mehreren Elementen pro Zeile zum Erstellen eines Rasters für einen Teil des Adapterinhalts ist unkompliziert.

2
adamp

Als Nachuntersuchung teile ich auch meine Schmerzen. In meiner App habe ich eine RecyclerView in einer NestedScrollView in einer CoordinatorLayout:

<CoordinatorLayout>
  <NestedScrollView id="@+id/content">

     .......

     <TextView Android:id="@+id/header"/>

     <RecyclerView Android:id="@+id/recyclerView"/>       

  </NestedScrollView>
</CoordinatorLayout>

Beim Öffnen der Aktivität hat die Seite natürlich die Recyclingansicht in der Mitte angezeigt. Keine der obigen Antworten funktionierte, daher kam mir folgende Lösung:

@Override
protected void onCreate( Bundle savedInstanceState ) {
  ....
  content.setOnScrollChangeListener( new NestedScrollView.OnScrollChangeListener() {
    @Override
    public void onScrollChange( NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY ) {
      Rect scrollBounds = new Rect();
      v.getHitRect( scrollBounds );
      if( header.getLocalVisibleRect( scrollBounds ) ){
        if( View.VISIBLE != recyclerView.getVisibility() ){
          recyclerView.setVisibility( View.VISIBLE );
          fillRecyclerViewSomehow();
        }
      }
    }
  }
}

@Override
protected void onResume() {
  ...
  recyclerView.setVisibility( View.GONE ); // this effectively suppresses the focusability
}

HTH

0
injecteer

Ein einfacher Weg, dies zu erreichen, besteht darin, eine ID für Ihre ScrollView in XML einzurichten

scrollView_main

Danach müssen Sie nur noch zu Ihrer Java-Datei gehen und sie wie eine normale Variable über der Prozedur onCreate als eine globale Variable wie diese deklarieren

ScrollView scrollView_main;

oK, jetzt ist es an der Zeit, zur Prozedur onCreate zu gehen und dies zu deklarieren, um eine Verbindung mit Ihrer ID aus der XML-Datei herzustellen

scrollView_main = (ScrollView)findViewById(R.id.scrollView_main);

und schließlich der Code, der dazu führt, dass Ihr ScrollView oben gescrollt wird, das ist Ihre Antwort

scrollView_main.smoothScrollTo(0,0); //set it on top
0

Wenn nichts funktioniert, setzen Sie dies einfach als erstes Element des einzigen untergeordneten Elements von scrollView:

<EditText
   Android:layout_width="0dp"
   Android:layout_height="0dp"/>

beispiel:

  <ScrollView
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content">

        <LinearLayout
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content">
            <EditText
                    Android:layout_width="0dp"
                    Android:layout_height="0dp"/>
            <!-- your other views  -->
        </LinearLayout>
</ScrollView>
0
Kishita

Ich habe einen Weg gefunden, dem GridView eine feste Größe in ScrollView zu geben und das Scrollen zu aktivieren . Auf diese Weise können Sie die gesamte ScrollView anzeigen, ohne alle Elemente der GridView scrollen zu müssen. Für mich ist es sinnvoller, wenn Sie eine ExpandableHeightGridView verwenden.

Dazu müssen Sie eine neue Klasse implementieren, die GridView erweitert und onTouchEvent () überschreibt, um requestDisallowInterceptTouchEvent (true) ..__ aufzurufen. Auf diese Weise hinterlässt die übergeordnete Ansicht die Berührungsereignisse für die Interaktion mit dem Grid.

GridViewScrollable.Java:

package com.example;
import Android.content.Context;
import Android.util.AttributeSet;
import Android.view.MotionEvent;
import Android.widget.GridView;

public class GridViewScrollable extends GridView {

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

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

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

    @Override
    public boolean onTouchEvent(MotionEvent ev){
        // Called when a child does not want this parent and its ancestors to intercept touch events.
        requestDisallowInterceptTouchEvent(true);
        return super.onTouchEvent(ev);
    }
}

Fügen Sie es in Ihrem Layout mit den gewünschten Merkmalen und Rändern in einer ScrollView hinzu:

<ScrollView 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:isScrollContainer="true" >

    <com.example.GridViewScrollable
    Android:id="@+id/myGVS"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:gravity="center"
    Android:numColumns="auto_fit"
    Android:stretchMode="columnWidth" />

</ScrollView>

Und hol es dir einfach in deine Aktivität:

GridViewScrollable myGridView = (GridViewScrollable) findViewById(R.id.myGVS);

Ich hoffe es hilft =)

0
Lionel T.