android - 当其中的 View 触发 Android 中的事件时无法滚动 ScrollView

标签 android drag-and-drop scrollview titanium-mobile

我正在使用 Titanium SDK 3.1.1,我的应用程序中的逻辑是这样的:

我有一个类似于 TableView 的 ScrollView,其中包含作为部分工作的 View ,每个部分包含可拖动的 View ,每个水平可拖动的 View 都有一个 touchstarttouchmovetouchend 事件来拖动它们。问题是,如果我将 ScrollView 的属性 canCancelEvents 设置为 false,我将无法滚动 ScrollView。这个问题不会在 iOS 中发生,只会在 Android 中发生。

我尝试将 Android 的 canCancelEvents 属性设置为 true,但是当滚动工作时,当我在 ScrollView 中拖动其中一个 View 时,如果有任何机会我垂直拖动它(可拖动 View 不会垂直拖动,只能水平拖动)然后 ScrollView 的滚动事件控制该事件并且拖动被中断。 这是我的代码:

// This function create a horizontal draggable View
function evaluationItem(item)
{
    var self = Ti.UI.createView({
        width:Ti.Platform.displayCaps.platformWidth, 
        height:88 + dpi
    });

    var backgroundWorkspace = Ti.UI.createView({
        top:0 + dpi, 
        left:0 + dpi, 
        backgroundColor:"#404040", 
        width:Ti.Platform.displayCaps.platformWidth, 
        height:'100%', 
        zIndex:0
    });

    var checkEvaluation = Ti.UI.createImageView({
        image:imagesPath + "CheckEvaluation.png", 
        opacity:0, 
        left:20 + dpi
    });

    var notYetEvaluation  = Ti.UI.createImageView({
        image:imagesPath + "NotYetEvaluation.png", 
        opacity:0, 
        right:20 + dpi
    });

    backgroundWorkspace.add(checkEvaluation);
    backgroundWorkspace.add(notYetEvaluation);

    var foregroundWorkspace = Ti.UI.createView({
        top:0 + dpi, 
        left:0 + dpi, 
        backgroundColor:"#FFFFFF", 
        width:Ti.Platform.displayCaps.platformWidth, 
        height:'100%', 
        zIndex:1
    });

    var foregroundWorkspaceDraggable = Ti.UI.createView({
        top:0 + dpi, 
        left:0 + dpi, 
        backgroundColor:"transparent", 
        width:Ti.Platform.displayCaps.platformWidth, 
        height:'100%', 
        zIndex:2
    });

    var curX, curY;
    var deltaX, deltaY;
    var currentPositionX, currentPositionY;
    var initialViewX = parseInt(foregroundWorkspace.getLeft()) , initialViewY = parseInt(foregroundWorkspace.getTop());
    var limitToTheRight = Ti.Platform.displayCaps.platformWidth/2.5;
    var limitToTheLeft = (-1)* Ti.Platform.displayCaps.platformWidth/2.5;   
    var neutralColor = "#404040";
    var positiveColor = "#79b715";
    var negativeColor = "#9e9e9e";

    // event for touchstart
    foregroundWorkspaceDraggable.addEventListener('touchstart', function(e) {
        curX = e.x;
        curY = e.y; 
});

    var hoveringOver = 0;
    // event for touchmove, this handles the dragging
    foregroundWorkspaceDraggable.addEventListener('touchmove', function(e) {

        var currentOpacity = currentPositionX / limitToTheRight;
        if(currentOpacity < 0)
            currentOpacity = 0;
        else if(currentOpacity > 1)
            currentOpacity = 1;
        checkEvaluation.setOpacity(currentOpacity);

        var currentOpacityNotYet = currentPositionX / limitToTheLeft;
        if(currentOpacityNotYet < 0)
            currentOpacityNotYet = 0;
        else if(currentOpacityNotYet > 1)
            currentOpacityNotYet = 1;
        notYetEvaluation.setOpacity(currentOpacityNotYet);

        deltaX = e.x - curX;
        currentPositionX = initialViewX + deltaX;

        if (currentPositionX > limitToTheRight) {
            if (hoveringOver != 1) {
                hoveringOver = 1;
                backgroundWorkspace.animate({
                    backgroundColor : positiveColor,
                    duration : 250
                });
            }
        } else if (currentPositionX <= limitToTheLeft) {
            if (hoveringOver != -1) {
                hoveringOver = -1;
                backgroundWorkspace.animate({
                    backgroundColor : negativeColor,
                    duration : 250
                });
            }
        } else {
            if (hoveringOver != 0) {
                hoveringOver = 0;
                backgroundWorkspace.animate({
                    backgroundColor : neutralColor,
                    duration : 250
                });
            }
        }
        foregroundWorkspace.setLeft(currentPositionX);
    });

    function recallControl()
    {
        foregroundWorkspace.animate({
            left : 0 + dpi,
            duration : 500
        });
    }

    // event for touchend, this handles where the view remains in the end
    foregroundWorkspaceDraggable.addEventListener("touchend", function(e){
        if (currentPositionX > limitToTheRight) {
            foregroundWorkspace.animate({
                left : Ti.Platform.displayCaps.platformWidth + dpi,
                duration : 500
            }, function() {
                self.animate({
                    height : 0 + dpi,
                    duration : 500
                });
            }); 
        } else if (currentPositionX <= limitToTheLeft) {
            foregroundWorkspace.animate({
                left : -Ti.Platform.displayCaps.platformWidth + dpi,
                duration : 500
            });
        } else {
            // alert('3');

            recallControl();
        }


    });

    var foregroundWorkspaceDecorator = Ti.UI.createView({
        width:Ti.UI.FILL, 
        height:1 + dpi, 
        backgroundColor:"#d8d8d8", 
        bottom:0 + dpi, 
        left:0 + dpi
    });

    foregroundWorkspace.add(foregroundWorkspaceDecorator);

    var evaluationIdView = Ti.UI.createView({
        width:20 + dpi, 
        height:'100%', 
        top:0 + dpi, 
        left:10 + dpi, 
        backgroundColor:"transparent"
    });

    var evaluationIdLabel = Ti.UI.createLabel({
        text : item.id + ".",
        font : {
            fontSize : 20 + dpi,
            fontWeight : "bold"
        },
        color : item.color
    });

    evaluationIdView.add(evaluationIdLabel);

    foregroundWorkspace.add(evaluationIdView);

    var evaluationContentLabel = Ti.UI.createLabel({
        text : "This is an evaluation,you can drag to the left or to the right and it will evaluate your kid",
        left : 40 + dpi,
        width : Ti.UI.FILL,
        right : 30 + dpi,
        font : {
            fontSize : 14 + dpi
        },
        color : "#7a7a7a"
    });

    foregroundWorkspace.add(evaluationContentLabel);

    self.add(backgroundWorkspace);
    self.add(foregroundWorkspace);
    self.add(foregroundWorkspaceDraggable);

    return self;    
}

// function that creates the sections for the ScrollView
function evaluationCategory(category)
{
    var backgroundColor = "#229ce5";

    switch(category.categoryType)
    {
        case 0: // blue
            backgroundColor = "#229ce5";
            break;
        case 1: // pink
            backgroundColor = "#c13a78";
            break;
        case 2: // orange
            backgroundColor = "#f87739";
            break;
        case 3: // green
            backgroundColor = "#79b715";            
            break;      
        case 4: // yellow
            backgroundColor = "#ffd024";            
            break;      
    }
    var self = Ti.UI.createView({
        height:Ti.UI.SIZE, 
        layout:"vertical"
    });

    var titleView = Ti.UI.createView({
        width:Ti.UI.FILL, 
        height:60 + dpi, 
        backgroundColor:backgroundColor
    });

    var titleViewLabel = Ti.UI.createLabel({
        text : "physical",
        font : {
            fontSize : 20 + dpi,
            fontWeight : "bold"
        },
        color : "#FFFFFF",
        textAlign : "left",
        width : Ti.UI.SIZE,
        height : Ti.UI.SIZE,
        left : 10 + dpi
    });

    titleView.add(titleViewLabel);

    self.add(titleView);

    var workspace = Ti.UI.createView({
        width:Ti.UI.FILL, 
        height:Ti.UI.SIZE,
        layout:"vertical"
    });

    for (var i = 0; i < 5; i++) {
        workspace.add(evaluationItem({
            id : i,
            color : backgroundColor
        }));
    }

    self.add(workspace);

    return self;
}
    // my ScrollView
    if(osname === 'android'){
        cancelEvents = true;
    }
    var scrollview = Ti.UI.createScrollView({
        top : 0,
        left : 0,
        contentHeight : Ti.UI.SIZE,
        scrollType : 'vertical',
        layout : 'vertical',
        showVerticalScrollIndicator : true,
        canCancelEvents:cancelEvents,
    });

    scrollview.add(evaluationCategory({
        categoryType : 0
    }));
    scrollview.add(evaluationCategory({
        categoryType : 1
    }));
    scrollview.add(evaluationCategory({
        categoryType : 2
    }));
    scrollview.add(evaluationCategory({
        categoryType : 3
    }));

Android 似乎在处理这种行为方面存在问题。我怎样才能使 ScrollView 在必须滚动时滚动,但在其中一个 View 周围拖动时不滚动?

最佳答案

我解决这个问题的方法是这样的:

touchmove 事件中,我只是将 ScrollView 的 scrollingEnabled 属性的值更改为 false,因此当我将其中一个元素拖动到其中时,滚动将被禁用。在 touchend 事件中,我再次启用了滚动。我传递了 ScrollView 的 setScrollingEnabled 函数的引用。

foregroundWorkspaceDraggable.addEventListener('touchmove', function(e) {

    setScrollingEnabled(false); //Added this

    var currentOpacity = currentPositionX / limitToTheRight;
    if(currentOpacity < 0)
        currentOpacity = 0;
    else if(currentOpacity > 1)
        currentOpacity = 1;
    checkEvaluation.setOpacity(currentOpacity);

    var currentOpacityNotYet = currentPositionX / limitToTheLeft;
    if(currentOpacityNotYet < 0)
        currentOpacityNotYet = 0;
    else if(currentOpacityNotYet > 1)
        currentOpacityNotYet = 1;
    notYetEvaluation.setOpacity(currentOpacityNotYet);

    deltaX = e.x - curX;
    currentPositionX = initialViewX + deltaX;

    if (currentPositionX > limitToTheRight) {
        if (hoveringOver != 1) {
            hoveringOver = 1;
            backgroundWorkspace.animate({
                backgroundColor : positiveColor,
                duration : 250
            });
        }
    } else if (currentPositionX <= limitToTheLeft) {
        if (hoveringOver != -1) {
            hoveringOver = -1;
            backgroundWorkspace.animate({
                backgroundColor : negativeColor,
                duration : 250
            });
        }
    } else {
        if (hoveringOver != 0) {
            hoveringOver = 0;
            backgroundWorkspace.animate({
                backgroundColor : neutralColor,
                duration : 250
            });
        }
    }
    foregroundWorkspace.setLeft(currentPositionX);
});

// event for touchend, this handles where the view remains in the end
foregroundWorkspaceDraggable.addEventListener("touchend", function(e){

    setScrollingEnabled(true); //Added this

    if (currentPositionX > limitToTheRight) {
        foregroundWorkspace.animate({
            left : Ti.Platform.displayCaps.platformWidth + dpi,
            duration : 500
        }, function() {
            self.animate({
                height : 0 + dpi,
                duration : 500
            });
        }); 
    } else if (currentPositionX <= limitToTheLeft) {
        foregroundWorkspace.animate({
            left : -Ti.Platform.displayCaps.platformWidth + dpi,
            duration : 500
        });
    } else {
        // alert('3');

        recallControl();
    }


});

如果您想在 ScrollView 中包含的 View 上处理此类事件但不希望中断 ScrollView 的事件,这对于 iOS 和 Android 来说都是一个很好的选择。

关于android - 当其中的 View 触发 Android 中的事件时无法滚动 ScrollView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18280040/

相关文章:

javascript - 无法在 Samsung Galaxy Tab 2 7.0 的默认浏览器上通过 youtube API 播放 youtube 视频

JFrame 上特定扩展名的 Java 拖放文件

c# - 在滚动条上的 WPF TreeView 中拖放

android - TextView 无法正确分割线

ScrollView 中的 Android SeekBar

reactjs - react native Web ScrollView 快照?

java - Facebook API 3.0 - NewPermissionRequest 错误

java - 如何使用 split function() 拆分此字符串

android - 来电后蓝牙 SCO 失败

Java Swing - 使用 TransferHandler 动态更改 JList