0

私の質問は、Android のドラッグ アンド ドロップ API に関連しています。私の質問が紛らわしかったら申し訳ありません。ただし、基本的に、ドラッグ アンド ドロップ操作を開始する場合はstartDrag()View. いくつかの情報でそれを渡し、次に、ドラッグされているOnDragListenerをリッスンする を渡します。Viewドラッグが開始されると、私の例では長押しすると、情報を受け入れることができるすべてのビューがシステムに登録され、この情報が受け入れられます。Drag and Dropの android docs でこれのいくつかをすばやく読むと、より理にかなっています。ただし、これまでに使用したことがなく、使用したいと仮定した場合の動作の簡単な概要です。

今、私の質問は本質的に私が遭遇した問題にあります。現在ドラッグされている のシステム情報も受け入れるViewwhileを作成したいと思います。問題は機能していないことです。ドラッグ操作が最初に開始されたときにビューが登録されていなかったので、私は驚きません。問題は、どうすればその場で登録できるかです。Androidのドキュメントは、最初に登録する方法を示していますが、すでに登録されている場合は示していません。onDragListenerView

MyDragListener (私の onDragListener のコード。現在はそれで遊んでいるだけです。)


protected class MyDragListener implements View.OnDragListener {

    @Override
    public boolean onDrag(View v, DragEvent event) {

        // Defines a variable to store the action type for the incoming event
        final int action = event.getAction();

        // Handles each of the expected events
            switch(action) {

                case DragEvent.ACTION_DRAG_STARTED:
                    // Determines if this View can accept the dragged data
                    /*The way it works is it essentially turns anything that can accept stuff to Blue 
                     * or whatever color. It also does not need to do anything in terms of showing it can accept anything.*/
                    if(event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
                        v.setBackgroundColor(Color.BLUE);

                        return (true);

                    } else {
                        return (false);
                    }
                //break;

                case DragEvent.ACTION_DRAG_ENTERED:
                    v.setBackgroundColor(Color.YELLOW);
                    Toast.makeText(v.getContext(), "Height is: "+v.getHeight(), Toast.LENGTH_SHORT).show();
                    return true;
                //break;

                case DragEvent.ACTION_DRAG_LOCATION:
                    //this is triggered right after ACTIN_DRAG_ENTERED
                    Log.d("TestActivity", "Location of the View you are dragging is x: "+event.getX()+" y: "+event.getY());
                    if(v.getHeight()-10 < event.getY() && v.getHeight() > event.getY()&& showingView == false ) {

                            //here you are checking if its in the lower bound of the view
                            LayoutInflater inflater = LayoutInflater.from(v.getContext());
                            LinearLayout layout = (LinearLayout)inflater.inflate(R.layout.some_text, table, false);
                            ((TextView)layout.findViewById(R.id.da_text)).setText("Some text");
                            layout.setTag("Empty");
                            layout.startDrag(ClipData.newPlainText("Empty", "Empty"), new View.DragShadowBuilder(), null, 0);
                            table.addView(layout, Integer.parseInt(v.getTag().toString())+1);
                        showingView = true;
                    }
                    return true;


                case DragEvent.ACTION_DRAG_EXITED:
                    v.setBackgroundColor(Color.BLUE);
                    return true;
                //break;

                case DragEvent.ACTION_DROP:
                    //this is obvious, gets the data in the view that was dropped
                    return true;

                case DragEvent.ACTION_DRAG_ENDED:
                    v.setBackgroundColor(Color.WHITE);
                    return true;


            }//end of switch

        return false;
    }

}//end of MyDragListener

編集 1

そこで、別のアプローチを試みました。LinearLayoutのアイテムになるホルダーを用意することにしましたTableLayout。そうすれば、OnDragListener必要になるまでそれを保持することができます。それは失敗しました。初めて使用したときは、TableLayoutに追加してもドラッグをリッスンしませんでしたが、ドラッグをドロップしてから長押しすると機能しました。したがって、それは目に見えないという事実と関係がありますが、そうではありません。したがって、デフォルトでは、非表示の場合は何もしません。それを起こさないようにする方法がわかりません。また、非表示の場合でも何かを実行できるようにします。何か案は?

4

2 に答える 2

4

私はこれが古い投稿であることを知っていますが、誰かが解決策/ハックを必要とする場合...私はこれに数時間苦労し、誰かに役立つかもしれないと思いました。

私の問題

アイテムをドラッグしているときにListViewを上下にスクロールさせようとしたときに、この問題が発生しました。問題は、スクロールすると、リストビューが新しい変換されたビューをグループビューにロードし、ドラッグの開始時にアクティブでなかったビュー(リストビューキャッシュにあり、ビューグループの子として関連付けられていない)が応答しなかったことです。ドラッグに。

ビューが最初のDRAG_STARTEDイベントを見逃したため、他のイベントを取得していなかったため、あなたはそれについて正しい考えを持っていました。

私はVIEW/VIEW GROUPのソースコードを調べていましたが、これをハックする方法はいくつかあります。最終的に、問題のあるビューの可視性を強制的に変更することで解決することにしました。これにより、イベントのチェーンが開始され、最終的には将来のDRAGEVENTS呼び出しにビューが含まれるようになります。

解決策:可視性変更ハック

したがって、新しいビューを親にアタッチした後、可視性をGONEに設定し、VISIBLEに戻すだけです。

child.setVisibility(View.GONE);
child.setVisibility(View.VISIBLE);

注:これは、a)ユーザーがまだドラッグしている間b)新しいビューがすでに親に追加されているときに実行します。

注:私にとっては、これで問題を解決できました。しかし、私の場合、同じコンテナ内にすでにドラッグイベントを受け入れている他のビューがありました。これがそのコンテナの最初の子である場合は、機能しない可能性があります。イベントを受け入れる子が含まれるコンテナに到達するまで、コンテナやコンテナのコンテナなどに対して同じトリックを実行することができます。

于 2013-02-26T19:25:48.623 に答える
0

古い質問ですが、私は非常に似たようなことをしようとしていました。私のために働いたよりクリーンなアプローチは次のとおりです。

  1. その中の個々のビューではなく、DragListener を ExpandableListView にアタッチします。

  2. 次に、DragEvent.ACTION_DRAG_LOCATION イベントの x、y 座標に基づいて、グループまたは子ビューを識別し、必要なアクションを実行します。

この方法では、ドラッグ イベントの開始時にグループ/子ビューを表示する必要はありません。

于 2016-08-29T20:43:44.230 に答える