- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个 SlidingUpPanelLayout将图像保存为顶 View ,以及需要滑动的 View 寻呼机。viewpager
有 3 个 fragment ,其中两个是 ListView 。所以我希望能够在拉起时扩展 View 寻呼机,一旦 View 寻呼机启动,我希望能够滚动 fragment 内的 scrollviews
。但是当下拉 scrollview
以防没有更多滚动时,我想开始折叠 viewpager
。所以请建议如何在拉动 ScrollView 时使 SlidingUpPanelLayout
折叠,以防没有更多内容可滚动?
这里我贴出我的一些代码:我已尝试通过以下方式捕获触摸事件并覆盖 SlidingUpPanel onInterceptTouchEvent
函数:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (isHandled) {
Log.i("interceptToch", "HEREEE");
return onTouchEvent(ev);
}
return false;
}
因此,当 SlidingUpPanelLayout 展开时,我设置了 isHandled = false
。因此,当 slidingUpPanelLayout 展开时,所有触摸事件都会传递给它的 subview 。
而且我还在 scrollView
中放置了 onTouchEvent
,以便解锁 SlidingUpPanelLayout.onInterceptTouchEvent
:
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
scroll = 0;
y = event.getY();
} else if (action == MotionEvent.ACTION_MOVE) {
if (scroll_view_summary.getScrollY() == 0 && event.getY() > y) {
scroll = scroll + 1;
if (scroll > 2) {
// the user has pulled the list and the slidingUpPanelLauout
// should be able to handle the toch events again
SlidingUpPanelLayoutCustom las =
((SaleDetailsActivity) getActivity()).getLayout();
las.setHandle(true);
scroll = 0;
return false;
}
}
}
return false;
}
但这行不通。问题是,一旦 scrollview.onTouch
事件在 MotionEvent.ACTION_MOVE
中,SlidingUpPanelLayout.onInterceptTouchEvent
就不会被调用。 SlidingUpPanelLayout.onInterceptTouchEvent
在 MotionEvent.ACTION_CANCEL
之后调用。这意味着无法将事件传递给 SlidingUpPanelLayout 并且面板无法折叠。
最佳答案
不幸的是,由于上述原因,您不能依赖 SlidingUpPanelLayout 的 onInterceptTouchEvent
方法。一旦 subview 的 onTouchEvent
方法返回 true
,将不再调用 onInterceptTouchEvent
。
我的解决方案有点复杂,但它可以让您准确地实现(我认为)您正在寻找的东西。单个触摸/拖动事件会将面板拖动到位,并在到位后继续滚动 subview 。同样,向下拖动时,单个触摸/拖动事件可以滚动 subview ,一旦完全滚动,将开始向下拖动面板。
2015-04-12 更新 SlidingUpPanelLayout 代码更新到版本 3.0.0。还考虑了 ListView 而不仅仅是 ScrollView。
1)在SlidingUpPanel的库工程的res/
文件夹中,打开attrs.xml
,添加
<attr name="scrollView" format="reference" />
您将使用它来标识一个 subview ,一旦面板被拖动到位,该 subview 将篡夺触摸事件。在您的布局 xml 文件中,您可以添加
sothree:scrollView="@+id/myScrollView"
或者你的 scrollView 的 ID 是什么。还要确保您没有声明 sothree:dragView
ID,这样整个 View 都是可拖动的。
其余的步骤都在SlidingUpPanelLayout.java
中完成...
2)声明以下变量:
View mScrollView;
int mScrollViewResId = -1;
boolean isChildHandlingTouch = false;
float mPrevMotionX;
float mPrevMotionY;
3) 在构造函数中,在 mDragViewResId
设置之后,添加以下行:
mScrollViewResId = ta.getResourceId(R.styleable.SlidingUpPanelLayout_scrollView, -1);
4)在onFinishInflate
中,添加如下代码:
if (mScrollViewResId != -1) {
mScrollView = findViewById(mScrollViewResId);
}
5)添加以下方法:
private boolean isScrollViewUnder(int x, int y) {
if (mScrollView == null)
return false;
int[] viewLocation = new int[2];
mScrollView.getLocationOnScreen(viewLocation);
int[] parentLocation = new int[2];
this.getLocationOnScreen(parentLocation);
int screenX = parentLocation[0] + x;
int screenY = parentLocation[1] + y;
return screenX >= viewLocation[0] &&
screenX < viewLocation[0] + mScrollView.getWidth() &&
screenY >= viewLocation[1] &&
screenY < viewLocation[1] + mScrollView.getHeight();
}
6)删除 onInterceptTouchEvent
。
7)将 onTouchEvent
修改为以下内容:
public boolean onTouchEvent(MotionEvent ev) {
if (!isEnabled() || !isTouchEnabled()) {
return super.onTouchEvent(ev);
}
try {
mDragHelper.processTouchEvent(ev);
final int action = ev.getAction();
boolean wantTouchEvents = false;
switch (action & MotionEventCompat.ACTION_MASK) {
case MotionEvent.ACTION_UP: {
final float x = ev.getX();
final float y = ev.getY();
final float dx = x - mInitialMotionX;
final float dy = y - mInitialMotionY;
final int slop = mDragHelper.getTouchSlop();
View dragView = mDragView != null ? mDragView : mSlideableView;
if (dx * dx + dy * dy < slop * slop &&
isDragViewUnder((int) x, (int) y) &&
!isScrollViewUnder((int) x, (int) y)) {
dragView.playSoundEffect(SoundEffectConstants.CLICK);
if ((PanelState.EXPANDED != mSlideState) && (PanelState.ANCHORED != mSlideState)) {
setPanelState(PanelState.ANCHORED);
} else {
setPanelState(PanelState.COLLAPSED);
}
break;
}
break;
}
}
return wantTouchEvents;
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
}
8)添加以下方法:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// Identify if we want to handle the touch event in this class.
// We do this here because we want to be able to handle the case
// where a child begins handling a touch event, but then the
// parent takes over. If we rely on onInterceptTouchEvent, we
// lose control of the touch as soon as the child handles the event.
if (mScrollView == null)
return super.dispatchTouchEvent(ev);
final int action = MotionEventCompat.getActionMasked(ev);
final float x = ev.getX();
final float y = ev.getY();
if (action == MotionEvent.ACTION_DOWN) {
// Go ahead and have the drag helper attempt to intercept
// the touch event. If it won't be dragging, we'll cancel it later.
mDragHelper.shouldInterceptTouchEvent(ev);
mInitialMotionX = mPrevMotionX = x;
mInitialMotionY = mPrevMotionY = y;
isChildHandlingTouch = false;
} else if (action == MotionEvent.ACTION_MOVE) {
float dx = x - mPrevMotionX;
float dy = y - mPrevMotionY;
mPrevMotionX = x;
mPrevMotionY = y;
// If the scroll view isn't under the touch, pass the
// event along to the dragView.
if (!isScrollViewUnder((int) x, (int) y))
return this.onTouchEvent(ev);
// Which direction (up or down) is the drag moving?
if (dy > 0) { // DOWN
// Is the child less than fully scrolled?
// Then let the child handle it.
if (isScrollViewScrolling()) {
isChildHandlingTouch = true;
return super.dispatchTouchEvent(ev);
}
// Was the child handling the touch previously?
// Then we need to rejigger things so that the
// drag panel gets a proper down event.
if (isChildHandlingTouch) {
// Send an 'UP' event to the child.
MotionEvent up = MotionEvent.obtain(ev);
up.setAction(MotionEvent.ACTION_UP);
super.dispatchTouchEvent(up);
up.recycle();
// Send a 'DOWN' event to the panel. (We'll cheat
// and hijack this one)
ev.setAction(MotionEvent.ACTION_DOWN);
}
isChildHandlingTouch = false;
return this.onTouchEvent(ev);
} else if (dy < 0) { // UP
// Is the panel less than fully expanded?
// Then we'll handle the drag here.
if (mSlideOffset < 1.0f) {
isChildHandlingTouch = false;
return this.onTouchEvent(ev);
}
// Was the panel handling the touch previously?
// Then we need to rejigger things so that the
// child gets a proper down event.
if (!isChildHandlingTouch) {
mDragHelper.cancel();
ev.setAction(MotionEvent.ACTION_DOWN);
}
isChildHandlingTouch = true;
return super.dispatchTouchEvent(ev);
}
} else if ((action == MotionEvent.ACTION_CANCEL) ||
(action == MotionEvent.ACTION_UP)) {
if (!isChildHandlingTouch) {
final float dx = x - mInitialMotionX;
final float dy = y - mInitialMotionY;
final int slop = mDragHelper.getTouchSlop();
if ((mIsUsingDragViewTouchEvents) && (dx * dx + dy * dy < slop * slop))
return super.dispatchTouchEvent(ev);
return this.onTouchEvent(ev);
}
}
// In all other cases, just let the default behavior take over.
return super.dispatchTouchEvent(ev);
}
9) 添加如下方法判断scrollView是否还在滚动。处理 ScrollView 和 ListView 的情况:
/**
* Computes the scroll position of the the scrollView, if set.
* @return
*/
private boolean isScrollViewScrolling() {
if (mScrollView == null)
return false;
// ScrollViews are scrolling when getScrollY() is a value greater than 0.
if (mScrollView instanceof ScrollView) {
return (mScrollView.getScrollY() > 0);
}
// ListViews are scrolling if the first child is not displayed, or if the first child has an offset > 0
else if (mScrollView instanceof ListView) {
ListView lv = (ListView) mScrollView;
if (lv.getFirstVisiblePosition() > 0)
return true;
View v = lv.getChildAt(0);
int top = (v == null) ? (0) : (-v.getTop() + lv.getFirstVisiblePosition() * lv.getHeight());
return top > 0;
}
return false;
}
10)(可选)添加以下方法以允许您在运行时设置 scrollView(即您想要在面板中放置一个 fragment ,并且该 fragment 的子级有一个 ScrollView/ListView想要滚动):
public void setScrollView(View scrollView) {
mScrollView = scrollView;
}
我们现在在这个类中完全管理触摸事件的处理。如果我们向上拖动面板并且它完全滑入到位,我们取消拖动然后在 mScrollView
子级中欺骗一个新的触摸。如果我们正在滚动 child 并到达顶部,我们会在 child 中欺骗一个“up”事件并欺骗一个新的拖动触摸。这也允许其他子部件上的点击事件。
已知问题我们欺骗的“向上”/“向下”事件可能会无意中触发 ScrollView 子元素上的点击事件。
关于android - SlidingUpPanelLayout 和 ScrollView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22478361/
我正在尝试创建一个类似于 BBC 新闻 native 应用程序的布局(使用known.js);一个垂直的ScrollView,其中有许多水平的ScrollView。我已经“工作”到了一切都渲染并且水平
我正在尝试创建一个类似于 BBC 新闻 native 应用程序的布局(使用known.js);一个垂直的ScrollView,其中有许多水平的ScrollView。我已经“工作”到了一切都渲染并且水平
我已经为以下问题寻找了很多答案,但没有找到合适的解决方案(也不是“不可能”)。我不想要双向 ScrollView! 我想要的只是拥有这样的东西: 如果我这样做(具有所需的布局属性),我会得到我的
我想使用 famo.us 标准 Scrollview但是有一个以不同速度滚动的背景图像以产生视差效果。 我想知道是否有一种方法可以连接到事件流,或者以某种方式将 Scrollviews 位置通过管道传
初始化程序中有一个带有 ScrollView(alwaysBounceVertical: false) 的属性,但我似乎找不到它了。 有谁知道如何禁用 SwiftUI ScrollView 上的垂直弹
在你说之前 “Google 说不要这样做” 请阅读我的所有问题!! 布局: ScrollView -> RelativeLayout -> ScrollView -> RelativeLayout 第
我想在 Windows 7 上创建一种体验(使用触摸),我可以在其中拥有一个只能垂直滚动的外部 ScrollViewer(它是屏幕的大小)。在那个 ScrollViewer 中,我将有几个其他的 Sc
我知道 Google 的人要求我们不要将 Scrollable View 放在另一个 Scrollable View 中,但他们是否有任何官方声明指示我们不要这样做? 最佳答案 试试这个 注意:这里
更新Xcode11 beta3后,我发现scrollview内部 View 的阴影会在边界处被切断,但在Xcode11 beta2中还可以。我只是使用底部填充来修复它,但我认为这不是一个好的解决方案。
我的 wpf 应用程序的结构如下: 我的目标是,如果 DataGrid 超过屏幕的高度来使用它自己的 Scrollviewer。目前只使用外部的 S
我在其他应用程序中使用了 ScrollView,只添加了 style={styles.container}与风格。然而,在这个应用程序中,我正在创建我的风格 alignItems:'flex-star
这是我的布局 xml。 ... 我已经尝试过此链接中的解决方案: ScrollView Inside ScrollVie
有没有办法在 nativescript 的 ScrollView 上隐藏滚动指示器?我试过 scrollBars='none' 和 css overflow='hidden' 但它不能同时工作。谢谢
所以我有一个 ScrollView ,里面有一个 TextView 。当文本的String长于屏幕宽度时,它只是在下一行中移动。我想通过在 ScrollView 中添加 HorizontalScr
我正在尝试在 android 的水平 ScrollView 中创建一个水平 ScrollView 。第一个水平 ScrollView 工作正常。当我尝试滚动时,第二个水平 ScrollView 不起作
我在同一布局中创建了两个 ScrollView。你可以说一个平行的 ScrollView 。我想手动滚动一个 ScrollView ,作为响应,另一个 ScrollView 应该以完全相同的方式滚动。
我在 android 中设计 UI,我在另一个 HorizontalScrollView 中有一个 HorizontalScrollView。但是,子 HorizontalScrollVi
我在另一个 ScrollView 中有 ScrollView 。我想滚动内部 ScrollView ,但外部 ScrollView 只滚动。如何解决这个问题? 谢谢。 最佳答案 sv01 =
我有两个 UIScrollView,如果用户在 ScrollView 中滚动,我想让另一个 ScrollView 也滚动。我已经阅读了一个解决方案,涉及将 pangesturerecognizer 从
我以编程方式创建了 UIScrollView 并向其中添加了多个 button。 它运行良好,没有任何问题。 但我需要通过复制先前 ScrollView 的内容来创建另一个 ScrollView 。
我是一名优秀的程序员,十分优秀!