Android - ListView inside Gallery makes the scrolling not Smooth

后端 未结 4 682
無奈伤痛
無奈伤痛 2020-12-30 14:35

I implemented a gallery, and inside it I have many listviews from left to right. For some reason Gallery works great with all views but not with listview. With listview, whe

相关标签:
4条回答
  • 2020-12-30 15:15

    I had a similar issue. The problem is that the ListView is intercepting touch events from your Gallery and modifying the view position in its block of code that deals with the vertical scrolling of the ListView. If only Gallery intercepted the touch event first... I consider this a bug in the Android source, but in the meantime you can fix the un-smooth scrolling by subclassing Gallery and using your subclass instead. This will do the trick:

    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);
        }
    }
    

    Also, set something like this in the activity that implements the gallery:

        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;
            }           
        });
    

    Finally, add onTouchEvent() to the activity itself:

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

    One final note... After implementing this fully, I found that from a usability perspective, it was better to extend ViewAnimator with a custom class I called AdaptableViewAnimator, that of course just had some adapter functionality baked-in, and embed the ListView inside it. It doesn't float around as much as the ListView-inside-Gallery.

    0 讨论(0)
  • 2020-12-30 15:15

    I had have the same problem. And the solution is less than simple.

      • Set the listview to be not focusable in touch mode.

      listView.setFocusableInTouchMode(false);

      • If you need focus, call it from onItemSelected listener.
    1. Use OnInterceptTouchEvent to get Touch Events from your child. And make some modification in onScroll and onTouchEvent of your 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;
      }
      
    0 讨论(0)
  • 2020-12-30 15:17

    This worked for me

    listView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
    
    0 讨论(0)
  • 2020-12-30 15:22

    Scrollable items inside of other scrollable items tends to have problems. I am not surprised that this does not work well.

    0 讨论(0)
提交回复
热议问题