10

我正在为 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);
    }
}

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

4

2 回答 2

7

Drag Events 最酷的地方在于,您也可以在 parent 中监听ViewGroup 它们。扩展GridView并覆盖onDragEvent到监视器DragEvent.ACTION_DRAG_LOCATION。在那里,获取拖动的 Y 坐标 ( event.getY())。确保从 中返回 true ACTION_DRAG_STARTED,否则您将不会在 中收到事件ACTION_DRAG_LOCATION

确定您的“命中框”,可能使用jaibatrik 建议的技术,或者仅使用 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"
    };
}
于 2013-05-02T23:06:18.110 回答
1

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

于 2013-04-22T20:17:09.550 回答