可以长按 Horizo​​ntalScrollView 的子项吗?

发布于 2024-12-12 23:55:56 字数 948 浏览 0 评论 0原文

我在基于 Horizo​​ntalScrollView 的自定义视图中实现长按时遇到问题。

Horizo​​ntalScrollView 有一个子 LinearLayout,而 LinearLayout 又具有一个子 View。视图通过 OnDraw() 将位图绘制到画布上。

我想让 Horizo​​ntalScrollView 正常滚动,无论是快还是慢。但是,如果用户将手指放在其中一张图像上(即使滚动),它将立即取消滚动并允许用户对所选图像执行功能。 (在这种特殊情况下,他们会在屏幕上移动图像,但它实际上可以是任意数量的函数。)

我已经尝试了处理每个层中的事件(true、false、super)的许多组合(< code>Horizo​​ntalScrollView 和 View),但似乎没有一个能 100% 工作。有些组合大部分都能达到目的,有些则只能部分达到目的,但它们似乎总是缺少一个或另一个功能(滚动、点击测试等)。

我得到的最接近的是在 Horizo​​ntalScrollView 的 onInterceptTouchEvent() 事件中返回 false,在 View 的 onTouch() 事件中返回 true。这允许滚动并在图像上注册命中测试。但是,它会立即将控制权传递回 Horizo​​ntalScrollView 的 onTouch() 事件。这使得无法检查图像是否已被按下几秒钟(长按)。

如果我在视图的 onTouch() 事件中返回 true,则命中测试会注册,并且我能够检查用户是否在 ACTION_MOVE 中长时间按下了图像。但是,Horizo​​ntalScrollView 不会滚动。

我是否遗漏了一些完全明显的东西,或者我只是选择了两种不能很好地结合在一起的观点?任何见解都值得赞赏。

I'm having a problem implementing a long press within my custom view, based on a HorizontalScrollView.

The HorizontalScrollView has a child LinearLayout, which in turn has a child View. The View draws bitmaps to the canvas via OnDraw().

I'd like to allow the HorizontalScrollView to scroll normally, either fast or slow. But, if the user holds their finger (even if scrolling) on one of the images, it would immediately cancel the scrolling and allow the user to perform a function with the selected image. (In this particular case, they'd be moving the image around the screen, but it could really be any number of functions.)

I've tried many combinations of handling the events (true, false, super) within each layer (HorizontalScrollView and View) but none seem to work 100%. Some combinations get there most of the way, some others part of the way, but they always seem to be missing one feature or another (scroll, hit test, etc.).

The closest I've gotten is to return false within the HorizontalScrollView's onInterceptTouchEvent() and true within the View's onTouch() event. This allows the scroll and also registers the hit test on the image. But, it immediately passes control back to the onTouch() event of the HorizontalScrollView. That makes it impossible to check if the image has been pressed for a number of seconds (long press).

If I return true within the View's onTouch() event, the hit test registers, and I'm able to check if the user has long pressed the image within ACTION_MOVE. But, then the HorizontalScrollView doesn't scroll.

Am I missing something completely obvious, or have I simply chosen two views that don't play well together? Any insight is appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烟若柳尘 2024-12-19 23:55:56

是的,

不知道你是否已经对此进行了排序,我已经将一些内容混在一起,我认为可以按照你的要求进行操作,如果没有,那么嘿嘿。

我有一个在水平滚动条中加载的活动,这可能不是最好的方法,但它对我有用:

HolderActivity 类(在 Horizo​​ntalScrollView 类中加载的那个)我有:

int selectedItem;
public boolean onLongClick(View v, int position) {
    selectedItem = position;
    openContextMenu(v);
    return true;
}

public boolean onItemClick(int position) {)//do what you want here on click (press)


@Override
public void onCreateContextMenu(ContextMenu menu, View v,
    ContextMenuInfo menuInfo) {

     String[] menuItems = {"Menu item 1 text", "Cancel"};
     for (int i = 0; i<menuItems.length; i++) {
       menu.add(Menu.NONE, i, i, menuItemsRemove[i]);
    }
     menu.setHeaderTitle("My menu title");
}

在你的 Horizo​​ntalScrollView 类的构造函数中,我传递了一个上下文在那里像这样:

public MyScroller(Context context) {
    super(context);
    this.context = context;
}

我有一个从 ArrayList 创建项目的方法,称为 setFeatureItems,如下所示:

public void setFeatureItems(ArrayList<MyListEntity> items){}

在这个方法中,我添加一个 GestureDetector 将上下文传递给每个项目,如下所示

mGestureDetector = new GestureDetector(context, new MyGestureDetector());

: MyGestureDetector 嵌套类引用了所有重要的parentActivity,如下所示:

class MyGestureDetector extends SimpleOnGestureListener {

        @Override
        public void onLongPress(MotionEvent arg0) {
            parentActivity.onLongClick(MyScroller.this, mActiveFeature);
        };

        @Override
        public boolean onSingleTapUp(MotionEvent arg0) {
            parentActivity.onItemClick(mActiveFeature);
            return true;
        };

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            try {
                //right to left
                if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    int featureWidth = getMeasuredWidth();
                    mActiveFeature = (mActiveFeature < (mItems.size() - 1))? mActiveFeature + 1:mItems.size() -1;
                    smoothScrollTo(mActiveFeature*featureWidth, 0);
                    return true;
                }
                //left to right
                else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    int featureWidth = getMeasuredWidth();
                    mActiveFeature = (mActiveFeature > 0)? mActiveFeature - 1:0;
                    smoothScrollTo(mActiveFeature*featureWidth, 0);
                    return true;
                }
            } catch (Exception e) {
                    Log.e("Fling", "There was an error processing the Fling event:" + e.getMessage());
            }
            return false;
        }
}

我已经从现有项目中删除了它,因此可能会有残留,我没有使它足够通用,我希望这有意义或有帮助,请告诉我如果我可以添加更多细节

right,

dont know if you have sorted this or not, I have mashed some bits together that I think do what you ask, if not then hey ho.

I have an activity that loads in the horizontal scroller, this might not be the best way but it works for me:

HolderActivity class (the one that loads in the HorizontalScrollView class) I have:

int selectedItem;
public boolean onLongClick(View v, int position) {
    selectedItem = position;
    openContextMenu(v);
    return true;
}

public boolean onItemClick(int position) {)//do what you want here on click (press)


@Override
public void onCreateContextMenu(ContextMenu menu, View v,
    ContextMenuInfo menuInfo) {

     String[] menuItems = {"Menu item 1 text", "Cancel"};
     for (int i = 0; i<menuItems.length; i++) {
       menu.add(Menu.NONE, i, i, menuItemsRemove[i]);
    }
     menu.setHeaderTitle("My menu title");
}

in your HorizontalScrollView class's constructor pass I pass through a context in there like so:

public MyScroller(Context context) {
    super(context);
    this.context = context;
}

I have a method for creating the items from an ArrayList called setFeatureItems like so:

public void setFeatureItems(ArrayList<MyListEntity> items){}

Within this method I add a GestureDetector passing the context to it to each item like so:

mGestureDetector = new GestureDetector(context, new MyGestureDetector());

And the MyGestureDetector nested class which has the reference to the all important parentActivity is like this:

class MyGestureDetector extends SimpleOnGestureListener {

        @Override
        public void onLongPress(MotionEvent arg0) {
            parentActivity.onLongClick(MyScroller.this, mActiveFeature);
        };

        @Override
        public boolean onSingleTapUp(MotionEvent arg0) {
            parentActivity.onItemClick(mActiveFeature);
            return true;
        };

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            try {
                //right to left
                if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    int featureWidth = getMeasuredWidth();
                    mActiveFeature = (mActiveFeature < (mItems.size() - 1))? mActiveFeature + 1:mItems.size() -1;
                    smoothScrollTo(mActiveFeature*featureWidth, 0);
                    return true;
                }
                //left to right
                else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    int featureWidth = getMeasuredWidth();
                    mActiveFeature = (mActiveFeature > 0)? mActiveFeature - 1:0;
                    smoothScrollTo(mActiveFeature*featureWidth, 0);
                    return true;
                }
            } catch (Exception e) {
                    Log.e("Fling", "There was an error processing the Fling event:" + e.getMessage());
            }
            return false;
        }
}

I have cut this from an existing proj so there might be remnants where I have not made it generic enough, I hope this makes sense or helps, let me know If i can add any more detail

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文