2

我在 Flex 移动应用程序(部署在 iOS 和 Android 上)中实现 Spark 列表时遇到了一个非常严重的问题。问题是,当一个项目被触摸时,列表选择并不总是有效。实际上,有时down状态已设置,但该项目从未被选中,而是先前选择的项目保持选中状态。

通过ListandListBase类,我发现我的列表确实收到了鼠标/触摸事件。List's确实被解雇了,实际上对于item_mouseDownHandler正确提交的选择和没有正确提交的选择表现相同。到目前为止,我发现的不同之处在于,对于不成功的选择,永远不会调用该commitProperties方法(属于),因此,也不会调用's ,从而导致选择不会改变。ListBaseListcommitSelection

有没有人更深入地了解为什么这不起作用?我会非常感谢任何帮助,因为我没有看到我自己解决这个问题。

对于想要重现该问题的任何人,请设置一个 Flex 移动项目并添加一个列表以使用简单的内联渲染器和一些通用对象进行查看,如下所示:

<s:List id="myList" width="100%" height="100%">
    <s:dataProvider>
        <s:ArrayCollection>
            <fx:Object label="Item1" />
                         .....
            <fx:Object label="Item30" />
        </s:ArrayCollection>
    </s:dataProvider>
</s:List>

然后用手指在设备上随机选择项目,看看会发生什么,即使你触摸屏幕也没有选择项目,有时会出现向下的颜色。

编辑:哦,不要专注于 3 outta 4,你必须多尝试 4 次才能看到问题,但我猜大约 75% 是一个不错的估计。

Edit2:由于其他人显然遇到了同样的问题,我在 Flex Jira 中提交了一个错误报告: https ://issues.apache.org/jira/browse/FLEX-33169

4

6 回答 6

4

我在 Apache Flex JIRA 上发布了我认为是这个随机问题的真正原因,并认为您可能会感兴趣。

https://issues.apache.org/jira/browse/FLEX-33169?focusedCommentId=13557088&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13557088

请让我知道你的想法。

于 2013-01-18T10:02:49.913 回答
1

我在提交的错误(https://issues.apache.org/jira/browse/FLEX-33169)上发布了这个,但我想我也会在这里发布这个信息:

我不太确定这是一个错误。

在带有鼠标的桌面上,列表选择鼠标按下时的项目。但是,在处于触摸交互模式的设备上,列表会在鼠标向上时选择项目。主要原因是用户可能想要滚动而不是实际选择项目(例如,选择项目可能会转换到新屏幕)。Down 与 selected 不同,一个 item 可能处于 down 状态,然后进入 downAndSelected 状态(然后是 selected 状态),也可能回到正常状态。down 和 selected 之间的区别是微妙的,但 down 是为了向用户显示他们在他们可能选择的东西之上,但 selected 意味着他们实际上已经选择了它。

在鼠标按下时,List 会跟踪单击了哪个项目,如果尚未开始滚动,则在鼠标向上时,该项目将被选中。您可以通过在 List.removeMouseHandlersForDragStart() 和 List.touchInteractionStartHandler() 中放置断点来查看发生了什么。如果滚动被触发,您将看到 List.touchInteractionStartHandler() 被调用。

如果这确实是问题,有办法阻止滚动发生。滚动不会立即开始,但它会等待确保用户已经移动了一定量的手指,然后再确定它确实是滚动。该逻辑在 TouchScrollHelper.sbRoot_mouseMoveHandler() 中。滚动所需的量可以通过 Scroller.mx_internal::minSlopInches 控制。您还可以通过在“touchInteractionStarting”(TouchInteractionEvent.TOUCH_INTERACTION_STARTING) 事件上调用 event.preventDefault() 来停止所有滚动。

如果这不是问题,我希望这会给你一些起点来调试正在发生的事情。

在旧的 Adob​​e wiki 上曾经有一个文档描述了其中一些行为(尽管没有那么多代码细节),但不幸的是,这似乎丢失了。希望 Adob​​e 的某个人可以抽出时间来复活它。

于 2012-08-22T03:16:12.130 回答
1

这个问题让我非常沮丧:它很严重,对用户体验的影响非常糟糕。(对于无法复制该问题的问题,请在 iPhone 或 Android 智能手机上进行测试,因为它似乎不会在 iPad 上发生)。所以在稍微调整之后......我希望我找到了一个解决方案,但我邀请大家进行更深入的测试。您必须使用以这种方式扩展的列表:

package com.panurge.mobile
{
    import flash.events.MouseEvent;

    import mx.core.IVisualElement;
    import mx.core.mx_internal;
    import mx.events.TouchInteractionEvent;

    import spark.components.List;
    import spark.events.IndexChangeEvent;
    import spark.events.RendererExistenceEvent;

    public class ListSelectionFix extends List
    {

        protected var itemMouseDown:Object;
        protected var changeEventDispatched:Boolean = false;


        use namespace mx_internal;

        public function ListSelectionFix()
        {
            super();
            // we need this to cancel previous selection if a scroll action occurs
            this.addEventListener(TouchInteractionEvent.TOUCH_INTERACTION_START, onInteractionStart);
            // we need this to preventing dispatch change event twice
            this.addEventListener(IndexChangeEvent.CHANGE, onIndexChange);
        }

        protected function onIndexChange(event:IndexChangeEvent):void
        {
            //trace("onIndexChanging", itemMouseDown, changeEventDispatched);
            if (itemMouseDown != null){

                if (changeEventDispatched){
                    changeEventDispatched = false;
                    event.preventDefault();
                }
            }
        }


        override protected function dataGroup_rendererAddHandler(event:RendererExistenceEvent):void
        {
            super.dataGroup_rendererAddHandler(event);

            var renderer:IVisualElement = event.renderer;

            if (!renderer)
                return;

            renderer.addEventListener(MouseEvent.MOUSE_UP, item_mouseUpHandler);
        }

        override protected function dataGroup_rendererRemoveHandler(event:RendererExistenceEvent):void
        {
            super.dataGroup_rendererRemoveHandler(event);

            var renderer:IVisualElement = event.renderer;

            if (!renderer)
                return;

            renderer.removeEventListener(MouseEvent.MOUSE_UP, item_mouseUpHandler);
        }

        override protected function item_mouseDownHandler(event:MouseEvent):void
        {

            itemMouseDown = event.currentTarget;

            //trace("item_mouseDownHandler");
            super.item_mouseDownHandler(event);
        }

        protected function onInteractionStart(event:TouchInteractionEvent):void
        {
            //trace("onInteractionStart");
            // set this to null when the scroll is starting again to avoid dispatch on item_mouseUpHandler
            itemMouseDown = null;

        }

        protected function item_mouseUpHandler(event:MouseEvent):void
        {
            if (itemMouseDown == null || event.isDefaultPrevented())
                return;

            //trace("item_mouseUpHandler");

            // if we are in the same item renderer then we can safely select the item touched
            if (event.currentTarget == itemMouseDown){

                var _selectedIndex:int = this.dataProvider.getItemIndex(event.currentTarget.data);
                setSelectedIndex(_selectedIndex, true);
                changeEventDispatched = true;
                itemMouseDown.selected = true;
                //event.stopImmediatePropagation();
                event.preventDefault();
                // is dispatch by setSelectedIndex()
                //dispatchEvent(new IndexChangeEvent(IndexChangeEvent.CHANGE));

            }
        }
    }

我希望它能解决。让我知道。

于 2012-10-07T22:58:48.530 回答
1

我有同样的问题。我想清楚:

  • 问题是:通过触摸从列表中选择项目,有时选择不会改变;发生这种情况时,您应该触摸 2 或 3 次才能更改选择;
  • 它只发生在 iPad 和 iPhone 设备上,不在模拟器中;
  • 难以重现,因为不容易理解受影响的情况;
  • 我可以假设它是在滚动动作之后特别发生的,并且肯定是轻触(但触摸发生了,所以“轻”不是问题......)

我没有解决方案,但我想与您分享,以强调这是一个影响用户体验的真正严重错误(我在应用商店也有负面评论...)。

再见

于 2012-08-13T13:01:48.980 回答
0

好的,初步解决方案(虽然我认为这更像是一种黑客攻击,因为我还不知道它是否不会引起其他问题)如下;

子类化火花列表,覆盖item_mouseDownHandler并专门设置选定的索引。

 override protected function item_mouseDownHandler(event:MouseEvent):void {
     setSelectedIndex((event.currentTarget as IItemRenderer).itemIndex);
 }

同样,这确实有效,但当然需要测试。会持续更新的!

于 2012-07-31T14:59:56.000 回答
0

我将代码(如下所示)与“默认”Flex 4.6 一起使用。我相信 Flex 4.6 自带 AIR 3.1,而不是你所说的 3.3

我无法复制所描述的问题。我在摩托罗拉 Xoom (Android 3)、HTC Evo 3D (Android 4)、第一代 iPad 和第三代 iPad 上进行了测试。

我确实注意到,有时在 iPad 上,如果我的手指按得太快或者如果我触摸了列表行之间的线,则不会选择一个项目;但是很难重现这一点。在这些情况下,从不设置停机状态;所以就好像媒体没有注册一样。我想这是因为在这种情况下我的触摸太轻了。

我的结论是其中之一:

  1. AIR 3.3 中存在一个在 AIR 3.1 中没有表现出来的错误
  2. iPad 2 上发生了一些奇怪的事情,而其他设备上没有发生
  3. Flex 4.6 和 AIR 3.3 的自定义合并有问题。

我在测试中使用的代码:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" applicationDPI="160">
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>

    <s:List id="myList" width="100%" height="100%">
        <s:dataProvider>
            <s:ArrayCollection>
                <fx:Object label="Item1" />
                <fx:Object label="Item2" />
                <fx:Object label="Item3" />
                <fx:Object label="Item4" />
                <fx:Object label="Item5" />
                <fx:Object label="Item6" />
                <fx:Object label="Item7" />
                <fx:Object label="Item8" />
                <fx:Object label="Item9" />
                <fx:Object label="Item10" />
                <fx:Object label="Item11" />
                <fx:Object label="Item12" />
                <fx:Object label="Item13" />
                <fx:Object label="Item14" />
                <fx:Object label="Item15" />
                <fx:Object label="Item16" />
                <fx:Object label="Item17" />
                <fx:Object label="Item18" />
                <fx:Object label="Item19" />
                <fx:Object label="Item20" />
                <fx:Object label="Item21" />
                <fx:Object label="Item22" />
                <fx:Object label="Item23" />
                <fx:Object label="Item24" />
                <fx:Object label="Item25" />
                <fx:Object label="Item26" />
                <fx:Object label="Item27" />
                <fx:Object label="Item28" />
                <fx:Object label="Item29" />
                <fx:Object label="Item30" />
            </s:ArrayCollection>
        </s:dataProvider>
    </s:List>

</s:Application>
于 2012-08-07T11:35:01.683 回答