如何在滚动和滚动触发的同时更改ScrollView内部视图的属性



我正在使用我的应用程序中的自定义Snapping scollview。它扩展了HorizontalScrollview并覆盖OnTouchEvent()。这用于在卷轴中间拍摄孩子的视图。还有一个足够宽的领先空间和尾随空间,因此可以将第一个和最后一个元素放在中间。
我使用两个类变量:

int mActiveFeature //Position of the element nearest to the middle, initially set to 1
List<Integer> mAvailableItems //IDs of contained menu elements in order without the spaces

这是我的OnTouchEvent:

@Override
public boolean onTouchEvent(MotionEvent event) {
    final int menuItemCount = this.mAvailableItems.size();
    switch(event.getAction()) {
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            float scrollX = getScrollX();
            float layoutWidth =
                    SnappingScroll.this.getWidth();
            float featureWidth =
                    (int) getResources().getDimension(R.dimen.item_width);
            float spaceWidth =
                    (int) getResources().getDimension(R.dimen.space_width);
            View oldItem =
                    findViewById(
                            SnappingScroll.this.mAvailableItems.get(
                                    SnappingScroll.this.mActiveFeature - 1
                            )
                    );
            oldItem.setAlpha(0.5f);
            oldItem.setClickable(false);
            SnappingScroll.this.mActiveFeature = (int) Math.min(
                    Math.round((scrollX - spaceWidth + (layoutWidth / 2) + (featureWidth / 2)) / featureWidth),
                    (float) menuItemCount
            );
            View newItem =
                    findViewById(
                            SnappingScroll.this.mAvailableItems.get(
                                    SnappingScroll.this.mActiveFeature - 1
                            )
                    );
            newItem.setAlpha(1.0f);
            newItem.setClickable(true);
            int scrollTo = (int) (
                    SnappingScroll.this.mActiveFeature * featureWidth
                            + spaceWidth
                            - layoutWidth / 2
                            - featureWidth / 2
            );
            smoothScrollTo(scrollTo, 0);
            return true;
        default:
            return super.onTouchEvent(event);
    }
}

这是我正在使用的XML文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:background="@android:color/black"
    android:orientation="vertical">
    <com.example.SnappingScroll
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center_horizontal">
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center_vertical">
            <Space
                android:id="@+id/leading_space"
                android:layout_width="@dimen/space_width"
                android:layout_height="match_parent" />
            <ImageView
                    android:id="@+id/item_1"
                    android:layout_width="@dimen/item_width"
                    android:layout_height="match_parent"
                    android:alpha="0.5"
                    android:clickable="false"
                    android:onClick="clickFunction"
                    android:src="@drawable/m_1"/>
            <ImageView
                    android:id="@+id/item_2"
                    android:layout_width="@dimen/item_width"
                    android:layout_height="match_parent"
                    android:alpha="0.5"
                    android:clickable="false"
                    android:onClick="clickFunction"
                    android:src="@drawable/m_2"/>
            <ImageView
                    android:id="@+id/item_3"
                    android:layout_width="@dimen/item_width"
                    android:layout_height="match_parent"
                    android:alpha="0.5"
                    android:clickable="false"
                    android:onClick="clickFunction"
                    android:src="@drawable/m_3"/>
            <Space
                android:id="@+id/trailing_space"
                android:layout_width="@dimen/space_width"
                android:layout_height="match_parent" />
        </LinearLayout>
    </com.example.SnappingScroll>
</LinearLayout>

我希望所有元素以一半透明,而不是可单击的,除了活动功能。目前,您可以滚动,然后放开时,视图捕捉到最近的元素。然后,最后一个被捕获到元素的停用,而新的元素被激活为。这很好,但是我希望用户看到,当他抬起手指时,Scrollview会捕捉到哪个元素。因此,应在滚动时完成新的活动功能的计算和更改透明度。这可能吗?我已经尝试将代码放在for MotionEvent.action_move的情况下,但是随后该视图根本没有滚动。当我将代码放入MotionEvent.action_scroll的情况下时,什么也没有发生,并且没有触发捕捉。


编辑:
首先,我将代码放入额外的OnTouchListener中,该代码是多余的,因此现在我覆盖了OnTouchEvent函数并相应地编辑了该问题。

在进行进一步的阅读和一些尝试之后错误,我想出了解决方案。
因此,首先,所需的MotionEvent是 Action_Move 。我以前尝试过,但是它没有起作用,因为我自己返回了 true false ,从不调用超级类的实现。因此,我总是返回 super.ontouchevent(event),因为这可以处理滚动本身。
只有我的 action_up action_cancel 处理不会打电话给超级类,因为这会做正常的滚动并且没有折断。

@Override
public boolean onTouchEvent(MotionEvent event) {
    final int menuItemCount = this.mAvailableItems.size();
    int oldFeature = this.mActiveFeature;
    float scrollX = getScrollX();
    float layoutWidth =
            SnappingScroll.this.getWidth();
    float featureWidth =
            (int) getResources().getDimension(R.dimen.item_width);
    float spaceWidth =
            (int) getResources().getDimension(R.dimen.space_width);
    View newItem, oldItem;
    switch(event.getAction()) {
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            newItem =
                    findViewById(
                            SnappingScroll.this.mAvailableItems.get(
                                    SnappingScroll.this.mActiveFeature - 1
                            )
                    );
            newItem.setClickable(true);
            int scrollTo = (int) (
                    SnappingScroll.this.mActiveFeature * featureWidth
                            + spaceWidth
                            - layoutWidth / 2
                            - featureWidth / 2
            );
            smoothScrollTo(scrollTo, 0);
            return true;
        case MotionEvent.ACTION_MOVE:
            SnappingScroll.this.mActiveFeature = (int) Math.min(
                    Math.round((scrollX - spaceWidth + (layoutWidth / 2) + (featureWidth / 2)) / featureWidth),
                    (float) menuItemCount
            );
            if(oldFeature == this.mActiveFeature) {
                return super.onTouchEvent(event);
            } else {
                oldItem =
                        findViewById(
                                SnappingScroll.this.mAvailableItems.get(
                                        oldFeature - 1
                                )
                        );
                oldItem.setAlpha(0.5f);
                oldItem.setClickable(false);
                newItem =
                        findViewById(
                                SnappingScroll.this.mAvailableItems.get(
                                        SnappingScroll.this.mActiveFeature - 1
                                )
                        );
                newItem.setAlpha(1.0f);
                return super.onTouchEvent(event);
            }
        default:
            return super.onTouchEvent(event);
    }
}

那么解决了最后一个问题。滚动浏览可以逃跑,因此抬起手指时,滚动不会停止。这会干扰扣子,所以我覆盖了 fling()方法:

@Override
public void fling (int velocityY)
{
    super.fling(0);
}

现在,没有fling弹,滚动浏览snapps到最中间的元素上。滚动时设置了透明度值,因此用户始终知道,滚动视图将符合哪个元素。

最新更新