6 votes

Android - ListView à l'intérieur de Gallery rend le défilement non fluide

J'ai implémenté une galerie et à l'intérieur j'ai plusieurs listviews de gauche à droite. Pour une raison quelconque, la galerie fonctionne très bien avec toutes les vues sauf avec listview. Avec listview, lorsque je défile sur la galerie, parfois j'ai de petits sauts.

Quelqu'un a une idée de comment résoudre ça?

Quelques notes: La galerie utilise un adaptateur pour savoir ce qu'il faut afficher, puis le listview est créé en fonction de l'adaptateur

Merci

8voto

jkschneider Points 4014

Je rencontre un problème similaire. Le problème est que le ListView intercepte les événements tactiles de votre Gallery et modifie la position de la vue dans son bloc de code qui traite du défilement vertical du ListView. Si seulement Gallery interceptait d'abord l'événement tactile... Je considère cela comme un bogue dans la source Android, mais en attendant, vous pouvez corriger le défilement non fluide en sous-classant Gallery et en utilisant votre sous-classe à la place. Cela fonctionnera :

public class BetterGallery extends Gallery {
    private boolean scrollingHorizontally = false;

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

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

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        super.onInterceptTouchEvent(ev);
        return scrollingHorizontally;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        scrollingHorizontally = true;
        return super.onScroll(e1, e2, distanceX, distanceY);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch(event.getAction()) {
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            scrollingHorizontally = false;
        }

        return super.onTouchEvent(event);
    }
}

De plus, définissez quelque chose comme ceci dans l'activité qui implémente la galerie :

    ListView listView = (ListView) view.findViewById(R.id.users);
    listView.setAdapter(userListAdapter);
    listView.setOnTouchListener(new OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
        galleryView.onTouchEvent(event);
        return false;
        }           
    });

Enfin, ajoutez onTouchEvent() à l'activité elle-même :

@Override
public boolean onTouchEvent(MotionEvent event) {
return galleryView.onTouchEvent(event);
}

Une dernière chose... Après avoir mis en œuvre cela complètement, j'ai trouvé qu'en termes d'utilisabilité, il était préférable d'étendre ViewAnimator avec une classe personnalisée que j'ai appelée AdaptableViewAnimator, qui avait bien sûr quelques fonctionnalités d'adaptateur intégrées, et d'incorporer le ListView à l'intérieur. Il ne flotte pas autant que le ListView à l'intérieur de Gallery.

2voto

CommonsWare Points 402670

Les éléments défilables à l'intérieur d'autres éléments défilables ont tendance à poser des problèmes. Je ne suis pas surpris que cela ne fonctionne pas bien.

1voto

Richard Points 246

J'ai eu le même problème. Et la solution est moins simple.

    • Définissez le listview pour ne pas être focusable en mode tactile.

    listView.setFocusableInTouchMode(false);

    • Si vous avez besoin de focus, appelez-le depuis l'auditeur onItemSelected.
  1. Utilisez OnInterceptTouchEvent pour obtenir des événements tactiles de votre enfant. Et apportez quelques modifications dans onScroll et onTouchEvent de votre Gallery

    OnItemSelectedListener mOnItemSelected = new OnItemSelectedListener()
    {   
        @Override
        public void onItemSelected(AdapterView parent, View view,
                int position, long id)
        {
          view.requestFocusFromTouch();
        }
        @Override
        public void onNothingSelected(AdapterView parent)
        {               
        }
    };
    
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        onTouchEvent(ev);
        return scrollingHorizontally;
    }
    
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        if(Math.abs(distanceX)>Math.abs(distanceY) || scrollingHorizontally == true){
            scrollingHorizontally = true;
            super.onScroll(e1, e2, distanceX, distanceY);
        }
        return scrollingHorizontally;
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch(event.getAction()) {
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            scrollingHorizontally = false;
            break;
        default:
                break;
        }
        super.onTouchEvent(event);
        return scrollingHorizontally;
    }

1voto

kiran Points 11

Cela a fonctionné pour moi

listView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X