拖动项目时滚动网格视图(作为阴影)

时间:2013-04-22 19:00:15

标签: java android drag-and-drop android-gridview

我正在开发api> 14我已经在GridView上实现了拖放功能。

但是,在将项目拖动到屏幕的顶部或底部时,GridView不会滚动。

我想让它在您移动到边缘时拖动项目的方向滚动,并在将项目移回屏幕的垂直中心时缓慢移动。

当然,这种功能在任何拖放时都应该是标准的吗?

无论如何,有没有人知道解决这个问题的最佳方法?

更新: 我实际上在互联网上找不到一个例子,甚至试图用拖动的网格项滚动(我在这里错过了什么?)更不用说解决我的问题了。

如何获取可拖动项目(显示为阴影)以滚动网格视图?我按如下方式分配拖动:

int gridChildPosition = position - mGridView.getFirstVisiblePosition();                     
ViewFlipper gridItem = (ViewFlipper) mGridView.getChildAt(gridChildPosition);

ClipData data = ClipData.newPlainText("", "");
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(gridItem);

if (mGridView.startDrag(data, shadowBuilder, gridItem, 0)) {

    int lastVisiblePosition = mGridView.getLastVisiblePosition() - mGridView.getFirstVisiblePosition();
    for (int i=0; i<=lastVisiblePosition; i++) {
        if (i == gridChildPosition) {
            continue;
        }
        mGridView.getChildAt(i).setOnDragListener(new GridItemDragListener(position));
        mGridView.getChildAt(i).setAlpha(0.4f);
    }
}

上面的代码创建了可拖动的阴影,当前所有其他项目都变暗了。但我不确定如何让阴影滚动网格视图。

2 个答案:

答案 0 :(得分:7)

Drag Events的一个很酷的事情是你可以在父ViewGroup 中听取它们。扩展GridView,并覆盖onDragEvent以监控DragEvent.ACTION_DRAG_LOCATION。在那里,获取拖动的Y坐标(event.getY())。确保从ACTION_DRAG_STARTED返回true,否则您将无法在ACTION_DRAG_LOCATION中收到该事件。

确定您的“命中框”,可能使用jaibatrik suggests的技术,或者只使用GridView测量高度的百分比。

使用smoothScrollByOffset(int offset)可能最有意义,这样就可以实现步进/指数滚动。意思是,用户在命中框中保留拖动项目的时间越长,偏移量就越大。

对于开源库/组件来说,这听起来很酷。 ; - )

修改

以下是您如何执行此操作的示例:

import android.app.Activity;
import android.content.ClipData;
import android.content.ClipData.Item;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.DragEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.GridView;

public class GridDragActivity extends Activity implements OnItemLongClickListener {

    private static final String TAG = "GridDragActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        MyGridView gridView = new MyGridView(this);
        gridView.setNumColumns(3);
        gridView.setOnItemLongClickListener(this);
        gridView.setAdapter(new ArrayAdapter<String>(
                this,
                android.R.layout.simple_list_item_1,
                COUNTRIES));

        setContentView(gridView);
    }

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position,
            long id) {

        ClipData data = ClipData.newPlainText((String) view.getTag(),
                String.valueOf(position));
        View.DragShadowBuilder shadow = new View.DragShadowBuilder(view);
        view.startDrag(data, shadow, null, 0);

        return true;
    }

    class MyGridView extends GridView {

        private static final int THRESHHOLD = 200;
        private static final int OFFSET = 10;

        public MyGridView(Context context) {
            super(context);
        }

        @Override
        public boolean onDragEvent(DragEvent event) {

            int height = getMeasuredHeight();

            switch (event.getAction()) {
                case DragEvent.ACTION_DRAG_STARTED:
                    return true;

                case DragEvent.ACTION_DRAG_LOCATION:

                    float y = event.getY();
                    if (height - y < THRESHHOLD) {
                        smoothScrollByOffset(OFFSET);
                    } else if (height - y > height - THRESHHOLD) {
                        smoothScrollByOffset(-OFFSET);
                    }

                    return true;

                case DragEvent.ACTION_DROP:

                    ClipData data = event.getClipData();
                    Item item = data.getItemAt(0);
                    int start = Integer.valueOf((String) item.getText());
                    int end = pointToPosition((int) event.getX(), (int) event.getY());

                    Log.i(TAG, "DROP started at = " + start + ", ended at = " + end);

                    return true;
            }

            return super.onDragEvent(event);
        }
    }

    static final String[] COUNTRIES = new String[] {
        "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
        "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
        "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
        "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
        "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
        "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil",
        "British Indian Ocean Territory",
        "British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
        "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
        "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
        "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
        "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
        "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica",
        "Dominican Republic",
        "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
        "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
        "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
        "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
        "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea",
        "Guinea-Bissau",
        "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong",
        "Hungary"
    };
}

答案 1 :(得分:1)

我认为您需要使用smoothScrollToPosition(int position)的方法smoothScrollByOffset(int offset)GridView。在屏幕的顶部和底部取两个矩形。如果在拖动时在thos矩形上接收到触摸事件,则滚动GridView。您可以使用getLastVisiblePosition()方法在任何给定时间获取最后一个可见位置。