2017-11-07 11 views
0

Ich habe eine TextView, die ich ein OnClickListener aktiviert haben. Wenn der Benutzer den Finger 7 Sekunden lang gedrückt hält und dann abhebt, öffnet sich ein Dialog, der beim Klicken auf die positive Schaltfläche eine Absicht auslöst und die Operation abbricht, wenn auf die negative Schaltfläche geklickt wird. Ich wollte einen visuellen Hinweis, wenn der Benutzer den TextView lange genug gedrückt hatte, so dass ich einen Handler und ein Runnable erstellte, das nach 7000ms triggert und die Hintergrundfarbe der Grundansicht geringfügig ändert. Es funktioniert zuerst gut. Wenn der Benutzer für 7 Sekunden gedrückt hält, ändert sich der Hintergrund und Sie können Ihren Finger heben, um den Dialog zu präsentieren. Wenn Sie abbrechen, wird alles wieder normal, einschließlich der Hintergrundfarbe. Das Problem ist, ich weiß nicht, wie Sie den Handler auf MotionEvent.ACTION_UP abbrechen, wenn der Benutzer vor 7 Sekunden den Finger gehoben hat. Hier ist mein Code:Abbrechen einer ausführbaren/Handler vor der Ausführung

View.OnTouchListener listener = new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 

       final Handler handler = new Handler(); 
       final Runnable runnable = new Runnable(){ 
        @Override 
        public void run(){ 
         Toast.makeText(mContext, "This is working", Toast.LENGTH_SHORT).show(); 
         mMainContainer.setBackgroundColor(getResources().getColor(R.color.alert_color)); 
        } 
       }; 

       View rootView = LayoutInflater.from(mContext).inflate(R.layout.admin_dialog, null); 

       if (event.getAction() == MotionEvent.ACTION_DOWN) { 
        // get the first touch in the series 
         start = System.currentTimeMillis(); 


        handler.postDelayed(runnable, 7000); 

       } 
       if (event.getAction() == MotionEvent.ACTION_UP) { 

        handler.removeCallbacks(runnable); 

        stop += System.currentTimeMillis(); 

        if ((stop - start) > 7000){ 

         // reset values 
         start = 0; 
         stop = 0; 

         final EditText password = (EditText)rootView.findViewById(R.id.admin_password_et); 

         AlertDialog.Builder dialog = new AlertDialog.Builder(mContext) 
           .setView(rootView) 
           .setTitle("Edit Configuration?") 
           .setPositiveButton(R.string.yes_button, new DialogInterface.OnClickListener() { 
            @Override 
            public void onClick(DialogInterface dialog, int which) { 
             int counter = 1; 
             if(password.getText().toString().equalsIgnoreCase("mq")){ 
              Intent intent = new Intent(mContext, MainActivity.class); 
              startActivity(intent); 
             } else { 
              mMainContainer.setBackgroundColor(getResources().getColor(android.R.color.background_light)); 
              Toast.makeText(mContext, "Wrong password, Access denied", Toast.LENGTH_SHORT) 
              .show(); 
              dialog.dismiss(); 
             } 
            } 
           }) 
           .setNegativeButton(R.string.no_button, new DialogInterface.OnClickListener() { 
            @Override 
            public void onClick(DialogInterface dialog, int which) { 
             mMainContainer.setBackgroundColor(getResources().getColor(android.R.color.background_light)); 
             dialog.dismiss(); 
            } 
           }); 
         dialog.create(); 
         dialog.show(); 
        } else { 

         // reset values 
         start = 0; 
         stop = 0; 
        } 
       } 

       return true; 
      } 
     }; 
     mAppTitle.setOnTouchListener(listener); 

Ich dachte, der Aufruf an handler.removeCallbacks (runnable); war die Antwort, aber es hat nicht funktioniert. Wie es jetzt ist, wenn Sie auf die Textansicht drücken und Ihren Finger vor 7 Sekunden abziehen, wird der Dialog nicht auftauchen, aber nach 7 Sekunden wird sich die Hintergrundfarbe noch ändern. Wie kann ich diesen Vorgang abbrechen? Muss ich das anders umsetzen?

Antwort

0

Ihr eigentliches Problem ist, dass Sie eine neue Instanz von Runnable jeden OnTouch zu schaffen, so dass der removeCallback nicht den überein Sie es dauern bis eine Lösung, ist dies:

Deklarieren Sie Runnable außerhalb des Methodenbereichs und initialisieren Sie es nur beim Herunterfahren.

Auch ich habe ACTION_CANCEL als UP hinzugefügt, weil dieses Verhalten passieren kann.

 View.OnTouchListener listener = new View.OnTouchListener() { 
     Runnable runnable; 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 

      final Handler handler = new Handler(); 

      View rootView = LayoutInflater.from(mContext).inflate(R.layout.admin_dialog, null); 

      if (event.getAction() == MotionEvent.ACTION_DOWN) { 
       // get the first touch in the series 
        start = System.currentTimeMillis(); 


      runnable = new Runnable(){ 
       @Override 
       public void run(){ 
        Toast.makeText(mContext, "This is working", Toast.LENGTH_SHORT).show(); 
        mMainContainer.setBackgroundColor(getResources().getColor(R.color.alert_color)); 
       } 
      }; 
       handler.postDelayed(runnable, 7000); 

      } 
      if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { 

       handler.removeCallbacks(runnable); 

       stop += System.currentTimeMillis(); 

       if ((stop - start) > 7000){ 

        // reset values 
        start = 0; 
        stop = 0; 

        final EditText password = (EditText)rootView.findViewById(R.id.admin_password_et); 

        AlertDialog.Builder dialog = new AlertDialog.Builder(mContext) 
          .setView(rootView) 
          .setTitle("Edit Configuration?") 
          .setPositiveButton(R.string.yes_button, new DialogInterface.OnClickListener() { 
           @Override 
           public void onClick(DialogInterface dialog, int which) { 
            int counter = 1; 
            if(password.getText().toString().equalsIgnoreCase("mq")){ 
             Intent intent = new Intent(mContext, MainActivity.class); 
             startActivity(intent); 
            } else { 
             mMainContainer.setBackgroundColor(getResources().getColor(android.R.color.background_light)); 
             Toast.makeText(mContext, "Wrong password, Access denied", Toast.LENGTH_SHORT) 
             .show(); 
             dialog.dismiss(); 
            } 
           } 
          }) 
          .setNegativeButton(R.string.no_button, new DialogInterface.OnClickListener() { 
           @Override 
           public void onClick(DialogInterface dialog, int which) { 
            mMainContainer.setBackgroundColor(getResources().getColor(android.R.color.background_light)); 
            dialog.dismiss(); 
           } 
          }); 
        dialog.create(); 
        dialog.show(); 
       } else { 

        // reset values 
        start = 0; 
        stop = 0; 
       } 
      } 

      return true; 
     } 
    }; 
    mAppTitle.setOnTouchListener(listener); 
+0

Ja, ich habe das herausgefunden. Ich gebe Ihnen Anerkennung für diese Antwort, weil Sie richtig erkannt haben, warum ich das Problem hatte. Das habe ich auch herausgefunden, aber ich habe auch die CountDownTimer-Klasse entdeckt, die Android bietet. Beide Lösungen funktionieren, aber ich hätte mich besser erklären sollen. Netter Job und danke :) –

0

Sie könnten versuchen, anstelle von 7000 als Wiederholung, Sie könnten ein viel kleineres Intervall tun, und stattdessen eine Zeit diff und so in Ihrem Handler Sie überprüfen, ob dieser Unterschied 7000ms überschritten hat. Sobald die Bedingung erfüllt ist, führen Sie Ihre Aktion aus. Hoffentlich habe ich deine Frage richtig verstanden.

Handler handler = new Handler(); 
      Runnable runnable = new Runnable() { 
       @Override 
       public void run() { 
        if (diff >7000) { 
         handler.removeCallbacks(runnable); 
        } else { 
         handler.postDelayed(runnable, 500); 
        } 
       } 
      }; 
+0

Haben Sie herausgefunden, was Sie in diesem Fall tun können? – DWndrer

0

Ich fand es heraus! Danke für die Hilfe von allen, aber ich habe herausgefunden, was ich für die beste Lösung halte. Ich habe ein CountDownTimer-Objekt außerhalb des OnTouchListener erstellt. Auf MotionEven.ACTION_UP Ich habe den Timer abgebrochen. Hier ist der Code, wenn es jemand hilft anderes:

final CountDownTimer timer = new CountDownTimer(7000, 1000) { 
      @Override 
      public void onTick(long millisUntilFinished) { 

      } 

      @Override 
      public void onFinish() { 
       mMainContainer.setBackgroundColor(getResources().getColor(R.color.alert_color)); 
      } 
     }; 

     View.OnTouchListener listener = new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 

       View rootView = LayoutInflater.from(mContext).inflate(R.layout.admin_dialog, null); 

       if (event.getAction() == MotionEvent.ACTION_DOWN) { 
        // get the first touch in the series 
        start = System.currentTimeMillis(); 
        timer.start(); 

       } 
       if (event.getAction() == MotionEvent.ACTION_UP) { 

        timer.cancel(); 

        stop += System.currentTimeMillis(); 

        if ((stop - start) > 7000) { 

         // reset values 
         start = 0; 
         stop = 0; 

         final EditText password = (EditText) rootView.findViewById(R.id.admin_password_et); 

         AlertDialog.Builder dialog = new AlertDialog.Builder(mContext) 
           .setView(rootView) 
           .setTitle("Edit Configuration?") 
           .setPositiveButton(R.string.yes_button, new DialogInterface.OnClickListener() { 
            @Override 
            public void onClick(DialogInterface dialog, int which) { 
             int counter = 1; 
             if (password.getText().toString().equalsIgnoreCase("mq")) { 
              Intent intent = new Intent(mContext, MainActivity.class); 
              startActivity(intent); 
             } else { 
              mMainContainer.setBackgroundColor(getResources().getColor(android.R.color.background_light)); 
              Toast.makeText(mContext, "Wrong password, Access denied", Toast.LENGTH_SHORT) 
                .show(); 
              dialog.dismiss(); 
             } 
            } 
           }) 
           .setNegativeButton(R.string.no_button, new DialogInterface.OnClickListener() { 
            @Override 
            public void onClick(DialogInterface dialog, int which) { 
             mMainContainer.setBackgroundColor(getResources().getColor(android.R.color.background_light)); 
             dialog.dismiss(); 
            } 
           }); 
         dialog.create(); 
         dialog.show(); 
        } else { 

         // reset values 
         start = 0; 
         stop = 0; 
        } 
       } 

       return true; 
      } 
     }; 
     mAppTitle.setOnTouchListener(listener); 
    } 
+0

Überprüfen Sie, ob meine Antwort funktioniert, wie Sie möchten –

Verwandte Themen