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

ViewGroup ドラッグ イベントの優れた点は、親でもリッスンできることです。を拡張GridViewし、オーバーライドonDragEventして監視しDragEvent.ACTION_DRAG_LOCATIONます。event.getY()そこで、ドラッグの Y 座標 ( ) を取得します。から 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 に答える