J'ai un problème avec une ScrollView qui contient à l'intérieur une GridView personnalisée et d'autres types de vues. La première fois que je commence l'activité, la ScrollView commence à son sommet, mais si je visite l'activité à d'autres moments, la ScrollView commence au début. J'ai utilisé la classe ExpandableHeightGridView qui se trouve dans ce lien pour mon GridView . Le code xml de la présentation Activité est celui-ci:
<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>
J'ai essayé d'utiliser le code scrollView.fullScroll(ScrollView.FOCUS_UP);
mais cela n'a pas fonctionné. Et même avec scrollView.scrollTo(0, 0);
je n'ai pas eu de succès . Le seul code qui a fonctionné était:
scrollView.post(new Runnable()
{
public void run() {
scrollViewLuogo.fullScroll(ScrollView.FOCUS_UP);
}
});
mais cela fait une animation rapide du haut du GridView au haut de l'écran et je ne l'aime pas.
Toute suggestion??
Solution:
Ok désolé si c'est une réponse tardive mais je suis tombé sur le même problème (seulement que j'utilisais ListView à la place) et avec un peu d'essais et d'erreurs j'ai trouvé la solution à ceci:
Le problème réside essentiellement dans le fait que l'enfant GridView/ListView demande automatiquement le focus parent (ScrollView) lorsque vous "hackez" et redimensionnez son contenu avec ExpandableHeightGridView, ce qui se produit après le rendu de la mise en page. essayer de le faire défiler vers le haut avec scrollTo () (survient APRÈS que la mise en page soit créée et APRÈS, gridView soit redimensionné, de sorte que tout rappel générique est inutile pour gérer cela par programme).
La solution la plus simple que j'ai trouvée consistait donc simplement à désactiver la propriété focusable sur ListView/GridView avec:
listView.setFocusable(false);
Ainsi, lorsque vous entrez pour la première fois dans l'activité, le focus est activé par défaut et ne repose pas sur Listview/GridView.
Et tout fonctionne bien =)
Le moyen le plus simple consiste à ajouter à la ScrollView parent les attributs XML suivants:
Android:descendantFocusability="beforeDescendants"
Android:focusableInTouchMode="true"
Cela signifie que ScrollView dans son ensemble sera celui qui aura le focus au lieu de tout conteneur interne lors du lancement de l'activité. Ceci est également utile, par exemple, lorsque vous avez un texte d'édition dans votre mise en page et que vous ne voulez pas qu'il soit mis en évidence immédiatement et affiché au clavier lors de la saisie d'un écran (principe identique).
Ainsi, votre ScrollView au-dessus de votre disposition ressemblerait à ceci:
<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" >
Ajoutez simplement ces deux lignes dans votre mise en page parent
Android: focusable = "true" Android: focusableInTouchMode = "true"
Essayez ceci, espérons que cela fonctionnera pour vous
Si vous voulez le faire défiler par programme en haut/en bas, vous pouvez le faire (c'est de ici ):
Pour le focus to down:
((ScrollView) findViewById(R.id.scrollView)).post(new Runnable() {
public void run() {
((ScrollView) findViewById(R.id.scrollView)).fullScroll(View.FOCUS_DOWN);
}
});
Pour le focus to top
((ScrollView) findViewById(R.id.scrollView)).post(new Runnable() {
public void run() {
((ScrollView) findViewById(R.id.scrollView)).fullScroll(View.FOCUS_UP);
}
});
Ajoutez simplement cette ligne de code dans l'enfant de ScrollView
Android:focusableInTouchMode="true"
ScrollView
Android:fitsSystemWindows="false"
Malheureusement, l'exemple que vous avez suivi est extrêmement pauvre. ListViews et GridViews ne doivent jamais être placés dans ScrollViews.
Le but de ScrollView est de donner une hauteur infinie à sa vue enfant. Le but de List/GridView est de prendre un ensemble de données potentiellement très volumineux et de ne générer que suffisamment de vues d’éléments pour occuper l’espace mis à sa disposition à la fois par souci d'efficacité. Les deux sont capables de faire défiler leur contenu sans l'autre.
Mettre une liste/GridView dans une ScrollView signifie "force imparable, rencontre un objet immuable". Soit vous avez vaincu le point de List/GridView ou vous avez vaincu le point de ScrollView en les combinant.
L'utilisation de vues d'en-tête/pied de page avec un ListView ou la concaténation du contenu des adaptateurs de liste en un seul adaptateur constitue un moyen plus efficace d'inclure d'autres contenus dans la même zone de défilement. La création d'éléments ListView contenant plusieurs éléments par ligne afin de constituer une grille pour une partie du contenu d'un adaptateur est simple.
En guise de suivi, je partagerai aussi ma douleur. Dans mon application, j'ai une RecyclerView
dans une NestedScrollView
dans une CoordinatorLayout
:
<CoordinatorLayout>
<NestedScrollView id="@+id/content">
.......
<TextView Android:id="@+id/header"/>
<RecyclerView Android:id="@+id/recyclerView"/>
</NestedScrollView>
</CoordinatorLayout>
Bien sûr, lors de l'ouverture de l'activité, la page a défilé pour inclure le recyclerView au milieu. Aucune des réponses ci-dessus n'a fonctionné et j'ai donc proposé la solution suivante:
@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
Un moyen simple d’y parvenir consiste à configurer un ID pour votre ScrollView en XML ... disons
scrollView_main
Après cela, il vous suffit d’aller dans votre fichier Java et de le déclarer comme une variable normale au-dessus de la procédure onCreate pour qu’elle soit globale, comme ceci
ScrollView scrollView_main;
ok, il est temps de passer à la procédure onCreate et de la déclarer, pour obtenir la connexion avec votre identifiant à partir d'un fichier XML
scrollView_main = (ScrollView)findViewById(R.id.scrollView_main);
et enfin le code qui fera le tour pour que votre ScrollView défile en haut, voici votre réponse
scrollView_main.smoothScrollTo(0,0); //set it on top
J'ai trouvé un moyen de donner au GridView une taille fixe dans ScrollView , et activer le défilement it. Cela vous permet de voir l'intégralité de ScrollView sans avoir à faire défiler tous les éléments de GridView, et il est plus logique pour moi que d'utiliser ExpandableHeightGridView.
Pour ce faire, vous devez implémenter une nouvelle classe étendant GridView et remplacer onTouchEvent () pour appeler requestDisallowInterceptTouchEvent (true) ..____. Ainsi, la vue parent laissera les événements tactiles d'interception de grille.
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);
}
}
Ajoutez-le dans votre mise en page avec les caractéristiques et les marges de votre choix, dans une ScrollView:
<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>
Et obtenez-le dans votre activité:
GridViewScrollable myGridView = (GridViewScrollable) findViewById(R.id.myGVS);
J'espère que ça aide =)