【问题标题】:Implement drag item to the screen edge feature实现拖动项目到屏幕边缘功能
【发布时间】:2015-12-18 14:31:51
【问题描述】:

当项目被拖动到屏幕边缘(左或右)附近时,我需要实现当前选项卡更改。

拖放功能和当前标签切换没有问题。我只是无法正确处理此事件 - 当拖动的项目靠近屏幕边缘时。

你会怎么做?

我尝试了什么:

<FrameLayout
    android:id="@+id/left_toggle_area"
    android:layout_width="30dp"
    android:layout_height="fill_parent"
    android:layout_alignParentStart="true"
    android:layout_alignParentLeft="true">
</FrameLayout>

<FrameLayout
    android:id="@+id/right_toggle_area"
    android:layout_width="30dp"
    android:layout_height="fill_parent"
    android:layout_alignParentEnd="true"
    android:layout_alignParentRight="true">
</FrameLayout>

<GridView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    ... />

这个想法是在切换区域拖动项目时以编程方式更改当前选项卡。

但该区域上的事件DragEvent.ACTION_DRAG_ENTERED 从未发生过,因为(我相信如此)GridView 占据了整个屏幕并简单地与切换区域重叠。

我已经尝试在触发拖动开始事件时将这些区域置于最前面。但由于某种原因,这不起作用。

FrameLayout toggleView = (FrameLayout) v;
        toggleView.bringToFront();
        toggleView.requestLayout();
        toggleView.invalidate();

如果有人遇到这样的问题,请分享您的经验。或者也许有另一个更好的解决方案。请给我一个提示。

【问题讨论】:

  • 我发布了我当前的解决方案。但仍然更喜欢使用有问题的拖动区域。因此,如果有人有想法,请欢迎。
  • 所以您不想放下并仍然更改标签?
  • 是的,我想用DragEvent.ACTION_DRAG_ENTERED事件改变当前标签
  • 你要拖动哪个项目,放在哪里?
  • 现在明白了......尝试使用带有视图标签的空视图容器而不是框架布局。

标签: android android-layout drag-and-drop android-viewpager


【解决方案1】:

我目前的解决方案(或多或少)是使用嵌套在PagerTabStrip标题中的TextView作为拖动区域。这种方法的最大缺点是那些切换区域由于某种原因太小了。 ENTER 事件仅在这些区域触发。

我相信这个解决方案对老式标签会很好。因此这里是代码。可能对某人有用。

1)。从PagerTabStrip解析TextViews

private ArrayList <TextView> titles;

...

public void setPager(PagerTabStrip mPagerTabStrip) {
    for (int i = 0; i < mPagerTabStrip.getChildCount(); ++i) {
        View nextChild = mPagerTabStrip.getChildAt(i);
        if (nextChild instanceof TextView) {
            TextView textViewToConvert = (TextView) nextChild;

            if (textViewToConvert.getText().toString().contains(TabsFragment.TAG_MONITOR)){ // I take only few tabs 
                if (!titles.contains(textViewToConvert)) {
                    titles.add(textViewToConvert);
                }
            }
        }
    }

}

public ArrayList<TextView> getTitles() {
    return titles;
}

在此操作之后,我有 3 个需要拖放导航的 TextView。

2)。将您的TextViews 列表传递给您实现DragListeners 的类:

 public void setUpDragNDropTabMoves(ArrayList<TextView> views) {
    if (views != null) {
        for (TextView tv : views){
            tv.setOnDragListener(TabToggleDragListener);
        }
    }
 }

3)。还有听众本身

 View.OnDragListener TabToggleDragListener = new View.OnDragListener() {
    @Override
    public boolean onDrag(View v, DragEvent event) {
        TextView toggleView = (TextView) v;
        String title = toggleView.getText().toString();

        switch (event.getAction()) {
            case DragEvent.ACTION_DROP:
                ...
                break;

            case DragEvent.ACTION_DRAG_ENTERED:
                int tabId = -1;
                //define which tab is destination
                if (title.contains(TabsFragment.TAG_MONITOR1)){
                    tabId = 1;
                } else if (title.contains(TabsFragment.TAG_MONITOR2)){
                    tabId = 2;
                } else if (title.contains(TabsFragment.TAG_MONITOR3)){
                    tabId = 3;
                }

                //send event to tab host fragment/activity and perform tab change to passed index
                //you may use EventBus or Otto for this. I used Local Broadcast
                BroadcastSender.sendMessageToUI(getContext(),
                        BroadcastSender.TABS_FRAGMENT,
                        BroadcastActions.TF_TOGGLE_TAB,
                        tabId 
                );
                break;
            case DragEvent.ACTION_DRAG_EXITED:
                ...
                break;

            case DragEvent.ACTION_DRAG_ENDED:
                ...
                break;
        }
        return true;
    }
};

【讨论】:

    【解决方案2】:

    我认为这三个视图(切换区域和GridView)的父级是RelativeLayout。首先,将GridView 替换为其父级的第一个子级。让布局的其余部分保持原样。

    其次,为了捕捉View.OnDragListener接口的drop事件,你需要在AndroidManifest.xml中设置最低SDK版本为11。之后,您可以将侦听器传递到切换区域:

    View.OnDragListener dragListener = new View.OnDragListener() {
        @Override
        public boolean onDrag(View v, DragEvent event) {
        // you can check for event.ACTION_DRAG_ENTERED here 
        return true;
        }
    };
    FrameLayout leftToggleArea = (FrameLayout) findViewById(R.id.left_toggle_area);
    leftToggleArea.setOnDragListener(dragListener);
    

    如果您仍有问题,请发布更多代码。

    【讨论】:

    • 拖动监听器的设置没有问题。我完全按照你在这里写的做了。问题是事件。ACTION_DRAG_ENTERED 永远不会在切换区域发生。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    • 2017-10-28
    • 1970-01-01
    • 2012-12-14
    • 2012-12-10
    相关资源
    最近更新 更多