一千萬個為什麽

搜索

Android/kindleドラッグフリーズ

私はこれがデバイスの問題か私のコードの問題かどうかは分かりませんが、相対レイアウトとイメージビューを使って簡単なドラッグ可能なソート可能なリストを作成しました。私はこのようにするための非常に具體的な理由があり、それは私の質問ではありません。

私が抱えている問題は、時々それが完全に私のアプリをフリーズすることです。アイテムがドラッグ狀態になってしまいます。私が指を持ち上げると、影(ドラッグ)オブジェクトはまだ畫面に殘っています。畫面に觸れると、その場所に移動します。これは約1分間続き、アプリを殺すか待つかのオプションに応答しないというエラーが表示されます。 logcatの唯一の有用なビットは次のとおりです:

12-09 14:23:13.157: W/WindowManager(16415): Drag is in progress but there is no drag window handle.

その後、アプリケーションがタイムアウトすると、これがエラーとして表示されます

12-09 14:59:09.782: E/ActivityManager(16415): ANR in com.appname.appname (com.appname.appname/.MainActivity)
12-09 14:59:09.782: E/ActivityManager(16415): Reason: keyDispatchingTimedOut

私はこのエラーメッセージを探知し、唯一の情報はドラッグリスナーのない人物であり、それを言っている別の人物はデバイスのタッチセンサーが追いつかないということでした。

理想的には、私はこのエラーを修正し、最初に起こらないようにしたいと思っています。私がすぐにドラッグするとほとんどの場合起こるようですが、ユーザーに素早くドラッグされないように頼むことはできません...そうですか?

また、ドラッグがアプリをフリーズしてドラッグを中斷していることを検出できる方法があります。タッチリスナーにタイマーを設定するのと同様に、2〜2回の割り込みのようなドラッグ位置のメッセージがない場合はドラッグしますか?タイマーのものはどうやってやるのか分かっていますが、凍っている間にドラッグを強制的に止める方法はわかりません。何か案は?

コードは次のとおりです:

設定

//happens once when the app loads
RelativeLayout trackList = (RelativeLayout) findViewById(R.id.nsTrackList1);    
trackList.setOnDragListener(new MyTrackDragListener(this));

//happens in a loop for each "track" (image view)
trackButton = new ImageView(this);
trackButton.setImageDrawable(nsPackages[trackId].banner[bannerSizeSelector]);
trackButton.setOnTouchListener(new MyTrackTouchListener());

オンタッチ

public class MyTrackTouchListener implements OnTouchListener {
    boolean isDragging=false;
    float prevX, prevY;
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if(motionEvent.getPointerCount() < 2 && !isDragging) return false;
        if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
            isDragging=false;
            prevX=0;
            prevY=0;
            return true;
        } else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
            if(isDragging) return true;
            boolean wasFirst = (prevX == 0 || prevY == 0);
            float theTotalDiff = Math.abs(prevX - motionEvent.getX()) + Math.abs(prevY - motionEvent.getY());
            prevX=motionEvent.getX();
            prevY=motionEvent.getY();
            if(wasFirst) return true;
            if(theTotalDiff <3) return true;
            ClipData data = ClipData.newPlainText("", "");
            DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);

            view.startDrag(data, shadowBuilder, view, 0);
            int thisViewId = view.getId();
            //hide view
            view.setVisibility(View.GONE);

            isDragging=true;    
            return true;
        } else if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
            isDragging=false;
            return true;
        }else {

            Integer thisAction = motionEvent.getAction();
            Log.d("looper","Motion action: "+thisAction.toString());
            return false;
        }
    }
} 

ドラッグ時

class MyTrackDragListener implements OnDragListener {
    public static boolean isDragging=false;
private MainActivity parent;

public MyTrackDragListener(MainActivity myAct){
    parent=myAct;
}       
    @Override
    public boolean onDrag(View v, DragEvent event) {
        int action = event.getAction();
        switch (event.getAction()) {
        case DragEvent.ACTION_DRAG_STARTED:
            isDragging=true;
           //do nothing
            return true;
        case DragEvent.ACTION_DROP:
            View view = (View) event.getLocalState();
            parent.doDropSort(view,(int) event.getY());
            return true;
        case DragEvent.ACTION_DRAG_ENDED:
            if(isDragging && event.getResult()==false){
                View view2 = (View) event.getLocalState();
                parent.doDropSort(view2,(int) event.getY(),true);
                return true;
            }
            isDragging=false;
            break;
        case DragEvent.ACTION_DRAG_LOCATION:
            parent.doDragHover((int) event.getY());
            return true;
        default:
            Log.d("looper","drag other... "+String.valueOf(event.getAction()));
        }
        return false;
    }
}

すでに試したことがいくつかあります

  • ドラッグリスナーを完全に削除する
  • onDragから常にtrueを返します。
  • 常にonDragからfalseを返します
  • 基本的には、ドラッグ&タッチでtrue/falseを返すすべての組み合わせ
  • 2本の指とAction_Move部分を削除し、代わりにAction_downでドラッグを開始する

同じ結果。ドラッグ&ドロップは完全に時間の約70%で動作し、突然上述のフリーズ動作を行います。時にはそれは最初の抗力に時にはそれはいくつかの後に時々です。私はおそらくドラッグ速度を除いて一貫したパターンに気付いた。私は素早くドラッグしているが、ドラッグする方向やドラッグする場所は問題にならないと思われる。

最佳答案

わーい!私はそれを考え出した。これは將來誰かを助けるための答えです。

私は最終的に一番上のリスト項目に絞り込みました(私がそれを逃したかどうかわかりません)。そして、それがこの行に絞り込まれたまで、コメントアウトし始めました:

view.setVisibility(View.GONE);

私のリストがどのように設定されたかは、相対レイアウト(下の項目を除く)でレイアウトプロパティBELOWを使用していました。ビューから一番上のアイテムを削除すると、二番目から一番上のアイテムは、可視性がGONEだったアイテムの下にあったので、何をすべきか分からなかった。解決策は、ビュー內の次の項目のパラメータを設定することでした。幸運にも、私は手動でトラックボタンのビューIDを設定します(ラベルなどのスクロールする他のビューもあります)ので、シーケンシャルです。だから私の修正はid + 1のアイテムを見つけて、このようにBELOWを0に設定してトップアイテムにすることでした...

// the top item in my list is ALWAYS view id 1
if(thisViewId == 1){
    ImageView nextTrackButton = (ImageView) trackList.findViewById(thisViewId+1);
    LayoutParams ntLP = (LayoutParams) nextTrackButton.getLayoutParams();
    ntLP.addRule(RelativeLayout.BELOW,0);
    nextTrackButton.setLayoutParams(ntLP);
}           

//hide view
view.setVisibility(View.GONE);

轉載註明原文: Android/kindleドラッグフリーズ