在Android中使用拖放功能制作scrollView自动滚动
我到处找,但找不到解决办法 我在scrollview中有一个视图(我们称之为myView)。myView比屏幕大。由于我能够在myView中获得手指的相对x、y位置,因此当手指进入某个上/下阈值时,我希望使scrollView自动滚动到上/下。 我有一些想法,即将拖动位置转换为屏幕位置,但这并没有解决这个问题 提前谢谢在Android中使用拖放功能制作scrollView自动滚动,android,android-scrollview,Android,Android Scrollview,我到处找,但找不到解决办法 我在scrollview中有一个视图(我们称之为myView)。myView比屏幕大。由于我能够在myView中获得手指的相对x、y位置,因此当手指进入某个上/下阈值时,我希望使scrollView自动滚动到上/下。 我有一些想法,即将拖动位置转换为屏幕位置,但这并没有解决这个问题 提前谢谢 干杯好吧,我自己想出来的 首先,我必须扩展ScrollView类并在ScrollViewListener上添加一个接口 public class MyScrollView ext
干杯好吧,我自己想出来的 首先,我必须扩展ScrollView类并在ScrollViewListener上添加一个接口
public class MyScrollView extends ScrollView {
private OnScrollViewListener mListener;
public MyScrollView(Context c, AttributeSet attrs) {
super(c, attrs);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (mListener != null) {
mListener.onScrollChanged((OnScrollViewListener) this);
}
}
public void setOnScrollViewListener(OnScrollViewListener listener) {
mListener = listener;
}
public static interface OnScrollViewListener {
public void onScrollChanged(OnScrollViewListener listener);
}
}
接下来在我的活动中,我插入了一个成员mScrollDistance,它指示
用户滚动的像素
public class ScrollActivity extends Activity {
private int mScrollDistance;
@Override
protected void OnCreate(...) {
...
final MyScrollView myScrollView = (MyScrollView) findViewById(R.id.scroll_view);
myScrollView.setOnScrollViewListener(new MyScrollView.OnScrollViewListener() {
public void onScrollChanged(OnScrollViewListener listener) {
mScrollDistance = listener.getScrollY();
}
}
// making an drag and drop in an view that is inside the MyScrollView
final LinearLayout myLayout = (LinearLayout)findViewById(R.id.linear_layout);
myLayout.setOnDragListener(new View.OnDragListener() {
public boolean onDrag (View v, DragEvent event) {
int action = event.getAction();
switch(action) {
case DragEvent.ACTION_DRAG_STARTED: {
}
case DragEvent.ACTION_DRAG_LOCATION: {
int y = Math.round(event.getY());
int translatedY = y - mScrollDistance;
int threshold = 50;
// make a scrolling up due the y has passed the threshold
if (translatedY < threshold) {
// make a scroll up by 30 px
myScrollView.scrollBy(0, -30);
}
// make a autoscrolling down due y has passed the 500 px border
if (translatedY + threshold > 500) {
// make a scroll down by 30 px
myScrollView.scrollBy(0, 30);
}
// listen for more actions here
// ...
}
}
}
}
公共类ScrollActivity扩展活动{
私密距离;
@凌驾
创建时受保护的void(…){
...
最终MyScrollView MyScrollView=(MyScrollView)findViewById(R.id.scroll\u视图);
myScrollView.setOnScrollViewListener(新的myScrollView.OnScrollViewListener(){
公共无效onScrollChanged(OnScrollViewListener侦听器){
mscrolldestance=listener.getScrollY();
}
}
//在MyScrollView内部的视图中进行拖放
最终线性布局myLayout=(线性布局)findViewById(R.id.linear\U布局);
myLayout.setOnDragListener(新视图.OnDragListener(){
公共布尔onDrag(视图v,DrageEvent事件){
int action=event.getAction();
开关(动作){
案例DrageEvent.ACTION\u DRAG\u已启动:{
}
case DragEvent.ACTION\u拖动位置:{
int y=Math.round(event.getY());
int translatedY=y-滚动距离;
int阈值=50;
//由于y已超过阈值,请向上滚动
if(translatedY<阈值){
//向上滚动30像素
myScrollView.scrollBy(0,-30);
}
//进行自动向下滚动,因为y已通过500像素边界
如果(平移Y+阈值>500){
//向下滚动30像素
myScrollView.scrollBy(0,30);
}
//在这里聆听更多的动作
// ...
}
}
}
}
现在,mScrollDistance始终会获得一个新值,拖动位置将转换为视图位置。
我对此进行了测试,它适用于比屏幕大的布局/视图
希望这能有所帮助。我想出了一个不同的解决方案,我对此很满意 我希望能够在ScrollView中拖放视图。当阴影到达ScrollView的边缘时,ScrollView需要自动上下滚动 我最终找到了一个解决方案,可以检测下降区域是否在scrollview中完全可见(具有100px的边距),并调整scroll view
@Override
public boolean onDrag(View view, DragEvent event) {
MainWidget dropZoneView = (MainWidget) view;
int action = event.getAction();
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
//(... other stuff happens here)
case DragEvent.ACTION_DRAG_LOCATION:
ScrollView mainScrollView = (ScrollView) findViewById(R.id.main_scroll);
int topOfDropZone = dropZoneView.getTop();
int bottomOfDropZone = dropZoneView.getBottom();
int scrollY = mainScrollView.getScrollY();
int scrollViewHeight = mainScrollView.getMeasuredHeight();
Log.d(LOG_TAG,"location: Scroll Y: "+ scrollY + " Scroll Y+Height: "+(scrollY + scrollViewHeight));
Log.d(LOG_TAG," top: "+ topOfDropZone +" bottom: "+bottomOfDropZone);
if (bottomOfDropZone > (scrollY + scrollViewHeight - 100))
mainScrollView.smoothScrollBy(0, 30);
if (topOfDropZone < (scrollY + 100))
mainScrollView.smoothScrollBy(0, -30);
break;
default:
break;
}
return true;
}
@覆盖
公共布尔onDrag(视图,DrageEvent事件){
MainWidget dropZoneView=(MainWidget)视图;
int action=event.getAction();
开关(动作){
案例DrageEvent.ACTION\u DRAG\u已启动:
//(…这里发生了其他事情)
case DragEvent.ACTION\u拖动位置:
ScrollView mainScrollView=(ScrollView)findViewById(R.id.main\u scroll);
int-topOfDropZone=dropZoneView.getTop();
int bottomOfDropZone=dropZoneView.getBottom();
int scrollY=mainSrollView.getScrollY();
int scrollViewHeight=mainScrollView.getMeasuredHeight();
Log.d(Log_标签,“位置:滚动Y:“+scrollY+”滚动Y+高度:”+(滚动+滚动视图高度));
日志d(日志标签,“顶部:”+topOfDropZone+“底部:”+topOfDropZone);
if(滚动区底部>(滚动+滚动视图高度-100))
mainScrollView.smoothScrollBy(0,30);
如果(topOfDropZone<(滚动+100))
mainScrollView.smoothScrollBy(0,-30);
打破
违约:
打破
}
返回true;
}
希望这有帮助!我在C中使用了计时器#
在拖动事件中
public bool OnDrag (View v, DragEvent e)
{
var dragshadow = new EventDateDragShadow (v);
switch (e.Action) {
case DragAction.Started:
return true;
case DragAction.Entered:
break;
case Android.Views.DragAction.Location:
if (e.GetY () < 90) {
ScrollCalendar.StartScroll (-15);
} else if (e.GetY () > yourScrollView.Height - 90) {
ScrollCalendar.StartScroll (15);
} else
ScrollCalendar.StopScroll ();
return (true);
case DragAction.Exited:
return true;
case DragAction.Drop:
return true;
case DragAction.Ended:
ScrollCalendar.StopScroll ();
v.SetOnDragListener (null);
return true;
}
return true;
}
更改StartScroll值和计时器。间隔以调整滚动速度。我修改了Tiago A的答案。 我也遇到了同样的问题,Tiago A的解决方案很小很简单,但是有一些限制,所以如果其他人需要,这可能会有所帮助。 多亏了蒂亚戈A
case DragEvent.ACTION_DRAG_LOCATION:
ScrollView myScrollView =findViewById(R.id.myScrollView);
int topOfDropZone = myScrollView.getChildAt(0).getTop();
int bottomOfDropZone = myScrollView.getChildAt(0).getBottom();
int scrollY = myScrollView.getScrollY();
int scrollViewHeight = myScrollView.getMeasuredHeight();
if (Math.round(event.getY()) > scrollViewHeight - (scrollViewHeight / 45))
if (bottomOfDropZone > (scrollY + scrollViewHeight - 100))
myScrollView.smoothScrollBy(0, 30);
if (Math.round(event.getY()) < (scrollViewHeight / 45))
if (topOfDropZone < (scrollY + 100))
myScrollView.smoothScrollBy(0, -30);
return true;
case DragEvent.ACTION\u拖动位置:
ScrollView myScrollView=findViewById(R.id.myScrollView);
int-topOfDropZone=mycrollview.getChildAt(0.getTop();
int bottomOfDropZone=mycrollview.getChildAt(0.getBottom();
int scrollY=myScrollView.getScrollY();
int scrollViewHeight=myScrollView.getMeasuredHeight();
if(Math.round(event.getY())>scrollViewHeight-(scrollViewHeight/45))
if(滚动区底部>(滚动+滚动视图高度-100))
myScrollView.smoothScrollBy(0,30);
if(Math.round(event.getY())<(scrollViewHeight/45))
如果(topOfDropZone<(滚动+100))
myScrollView.smoothScrollBy(0,-30);
返回true;
感谢您的想法,尽管您不必为自定义ScrollView付出全部努力。您只需使用普通ScrollView的getScrollY()即可获得mScrollDistance,而无需使用自定义ScrollView和侦听器等工具方法计算translatedY变量时使用。我意识到,只有当只有一个元素需要拖动时,您的解决方案才会起作用,并且最终得到一个完全不同的解决方案,该解决方案基于重写dispatchDragEvent()public class ScrollCalendar
{
private ScrollView Calendar;
private System.Timers.Timer Timer;
private int ScrollDistance;
public ScrollCalendar(ScrollView calendar)
{
Calendar = calendar;
Timer = new System.Timers.Timer();
Timer.Elapsed+=new ElapsedEventHandler(Scroll);
Timer.Interval = 50;
}
public void StartScroll(int scrollDistance)
{
if (Timer.Enabled) {
return;
}
ScrollDistance = scrollDistance;
Timer.Enabled = true;
}
public void StopScroll()
{
Timer.Enabled = false;
}
private void Scroll(object source, ElapsedEventArgs e)
{
Calendar.SmoothScrollBy (0, ScrollDistance);
}
}
case DragEvent.ACTION_DRAG_LOCATION:
ScrollView myScrollView =findViewById(R.id.myScrollView);
int topOfDropZone = myScrollView.getChildAt(0).getTop();
int bottomOfDropZone = myScrollView.getChildAt(0).getBottom();
int scrollY = myScrollView.getScrollY();
int scrollViewHeight = myScrollView.getMeasuredHeight();
if (Math.round(event.getY()) > scrollViewHeight - (scrollViewHeight / 45))
if (bottomOfDropZone > (scrollY + scrollViewHeight - 100))
myScrollView.smoothScrollBy(0, 30);
if (Math.round(event.getY()) < (scrollViewHeight / 45))
if (topOfDropZone < (scrollY + 100))
myScrollView.smoothScrollBy(0, -30);
return true;