Android - способ получить информацию, когда представление отображается в пределах прокрутки? - PullRequest
3 голосов
/ 24 марта 2012

У меня простой вопрос:

предположим, у меня есть некоторые виды на scrollView (или горизонтальныйScrollView). Есть ли способ добавить слушателя, который скажет мне, когда такой вид попадает внутрь и за пределы видимой области?

единственный похожий вопрос, который я видел, это: Android: как проверить, виден ли вид изнутри ScrollView? но я хочу получать информацию, когда такое событие происходит (становится скрытым / видимым).

Ответы [ 3 ]

3 голосов
/ 19 февраля 2014

Подклассы классов представления, которые вы используете (я сделал это для ImageView, так как я только добавлял их в свое представление прокрутки):

public class PeekImageView extends ImageView implements ViewTreeObserver.OnScrollChangedListener {
    private static final String LOG_TAG = "PeekImageView";
    private InViewportListener inViewportListener;
    private boolean isInViewport = false;

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

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

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

    public interface InViewportListener {
        void onViewportEnter(PeekImageView view);
        void onViewportExit(PeekImageView view);
    }

    public void setInViewportListener(InViewportListener listener) {
        this.inViewportListener = listener;
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        ViewTreeObserver vto = getViewTreeObserver();
        if (vto != null) {
            vto.addOnScrollChangedListener(this);
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        ViewTreeObserver vto = getViewTreeObserver();
        if (vto != null) {
            vto.removeOnScrollChangedListener(this);
        }
    }

    @Override
    public void onScrollChanged() {
        Rect bounds = new Rect();
        boolean inViewport = getLocalVisibleRect(bounds);
        Log.d(LOG_TAG, "is in view " + bounds + " : " + inViewport + " ; " + bounds);
        if (inViewportListener != null && isInViewport != inViewport) {
            if (inViewport) {
                inViewportListener.onViewportEnter(this);
            } else {
                inViewportListener.onViewportExit(this);
            }
        }
        isInViewport = inViewport;
    }
}

Присоединение InViewportListener к экземпляру этого PeekImageViewбудет получать уведомления, когда представление входит или покидает видимую часть окна (область просмотра).

1 голос
/ 09 июня 2012

Вы можете сделать что-то вроде:

1) сохранить список / массив представлений, содержащихся в вашем ScrollView.

2) Установите прослушиватель в представлении прокрутки для случая, когда прокрутка изменена: Синхронизация позиций прокрутки ScrollView - android

3) В цикле прослушивания этих представлений с использованием Android: как проверить, виден ли вид изнутри ScrollView? метод, чтобы увидеть, исчезли ли они с экрана

Это базовый метод, но он будет работать, скорость зависит от того, что на вашем экране и т. Д., Но он направляет вас в правильном направлении

0 голосов
/ 20 февраля 2014

Я нашел хороший способ получать уведомления о том, о чем я спрашивал здесь.

он работает для scrollView с вертикальным LinearLayout, но если вы хотите, вы можете заставить его работать и в других случаях,в зависимости от случая.

Я не уверен, должен ли я обрабатывать метод onSizeChanged (), и если да, что там делать, но во всех других случаях этот код работает нормально.

вот код:

MainActivity.java (для тестирования):

public class MainActivity extends Activity
  {
  @Override
  protected void onCreate(final Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final CustomScrollView scrollView=(CustomScrollView)findViewById(R.id.scrollView1);
    scrollView.setOnChildViewVisibilityChangedListener(new onChildViewVisibilityChangedListener()
      {
        @Override
        public void onChildViewVisibilityChanged(final int index,final View v,final boolean becameVisible)
          {
          Log.d("Applog","index:"+index+" visible:"+becameVisible);
          }
      });
    final ViewGroup container=(ViewGroup)findViewById(R.id.linearLayout);
    for(int i=0;i<20;++i)
      {
      final TextView tv=new TextView(this);
      tv.setText("item "+i);
      tv.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,300));
      container.addView(tv);
      }
    }
  }

activity_main.xml

<RelativeLayout 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" >

    <com.example.scrollviewvisibilitydetector.CustomScrollView
        android:id="@+id/scrollView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"  >

        <LinearLayout android:id="@+id/linearLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >
        </LinearLayout>
    </com.example.scrollviewvisibilitydetector.CustomScrollView>

</RelativeLayout>

CustomScrollView.java (реальная сделка ...):

public class CustomScrollView extends ScrollView
  {
  Set<Integer>                         _shownViewsIndices =new HashSet<Integer>();
  onChildViewVisibilityChangedListener _onChildViewVisibilityChangedListener;

  public interface onChildViewVisibilityChangedListener
    {
    public void onChildViewVisibilityChanged(int index,View v,boolean becameVisible);
    }

  public CustomScrollView(final Context context)
    {
    super(context);
    }

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

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

  public void setOnChildViewVisibilityChangedListener(final onChildViewVisibilityChangedListener onChildViewVisibilityChangedListener)
    {
    _onChildViewVisibilityChangedListener=onChildViewVisibilityChangedListener;
    }

  @Override
  protected void onLayout(final boolean changed,final int l,final int t,final int r,final int b)
    {
    super.onLayout(changed,l,t,r,b);
    checkViewsVisibility(l,t);
    }

  private void checkViewsVisibility(final int l,final int t)
    {
    final ViewGroup viewGroup=(ViewGroup)getChildAt(0);
    final int childCount=viewGroup.getChildCount();
    if(childCount==0)
      return;
    final int parentBottom=t+getHeight();
    // prepare to use binary search to find a view that is inside the bounds
    int min=0,max=childCount-1,piv=-1;
    int childTop,childBottom;
    View v;
    // check previously shown views
    for(final Iterator<Integer> iterator=_shownViewsIndices.iterator();iterator.hasNext();)
      {
      final Integer cur=iterator.next();
      v=viewGroup.getChildAt(cur);
      childTop=v.getTop();
      childBottom=v.getBottom();
      if(childTop<=parentBottom&&childBottom>=t)
        {
        if(piv==-1)
          piv=cur;
        }
      else
        {
        if(_onChildViewVisibilityChangedListener!=null)
          _onChildViewVisibilityChangedListener.onChildViewVisibilityChanged(cur,v,false);
        iterator.remove();
        }
      }
    if(piv==-1)
      {
      // check first view
      v=viewGroup.getChildAt(min);
      childTop=v.getTop();
      childBottom=v.getBottom();
      if(childTop<=parentBottom&&childBottom>=t)
        piv=min;
      else
        {
        // check last view
        v=viewGroup.getChildAt(max);
        childTop=v.getTop();
        childBottom=v.getBottom();
        if(childTop<=parentBottom&&childBottom>=t)
          piv=min;
        }
      if(piv==-1)
        while(true)
          {
          piv=(min+max)/2;
          v=viewGroup.getChildAt(piv);
          childTop=v.getTop();
          childBottom=v.getBottom();
          if(childTop<=parentBottom&&childBottom>=t)
            break;
          if(max-min==1)
            return;
          if(childBottom<t)
            // view above bounds
            min=piv;
          else max=piv;
          }
      }
    //
    for(int i=piv;i<childCount;++i)
      {
      v=viewGroup.getChildAt(i);
      childTop=v.getTop();
      childBottom=v.getBottom();
      // _shownViewsIndices.
      if(childTop<=parentBottom&&childBottom>=t&&!_shownViewsIndices.contains(i))
        {
        _shownViewsIndices.add(i);
        if(_onChildViewVisibilityChangedListener!=null)
          _onChildViewVisibilityChangedListener.onChildViewVisibilityChanged(i,v,true);
        }
      }
    for(int i=piv-1;i>=0;--i)
      {
      v=viewGroup.getChildAt(i);
      childTop=v.getTop();
      childBottom=v.getBottom();
      if(childTop<=parentBottom&&childBottom>=t&&!_shownViewsIndices.contains(i))
        {
        _shownViewsIndices.add(i);
        if(_onChildViewVisibilityChangedListener!=null)
          _onChildViewVisibilityChangedListener.onChildViewVisibilityChanged(i,v,true);
        }
      }
    }

  @Override
  protected void onScrollChanged(final int l,final int t,final int oldl,final int oldt)
    {
    super.onScrollChanged(l,t,oldl,oldt);
    checkViewsVisibility(l,t);
    }
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...