2017-11-07 40 views
0

onClickListener를 설정 한 textView가 있습니다. 사용자가 7 초 동안 손가락을 뗀 상태에서 들어 올리면 양수 버튼을 클릭하면 의도를 벗어난 대화 상자가 표시되고 음수 버튼을 클릭하면 작업이 취소됩니다. 사용자가 textView를 오랫동안 누르고있을 때 시각적 큐를 원했기 때문에 7000ms 후에 트리거하고 루트 뷰의 배경색을 약간 변경하는 핸들러와 runnable을 만들었습니다. 처음에는 훌륭하게 작동합니다. 사용자가 7 초 동안 누르고 있으면 배경이 바뀌고 손가락을 들어서 대화 상자를 표시 할 수 있습니다. 취소하면 모든 것이 배경색을 포함하여 정상으로 돌아갑니다. 문제는 사용자가 7 초 전에 손가락을 떼면 MotionEvent.ACTION_UP에서 처리기를 취소하는 방법을 모른다는 것입니다. 여기 내 코드입니다 :실행 전에 실행 파일/처리기 취소

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); 

내가 handler.removeCallbacks 호출 (실행 가능한)를 생각했다; 대답 이었지만 작동하지 않았습니다. 텍스트 뷰를 누르고 7 초 전에 손가락을 떼면 대화 상자가 나타나지 않지만 7 초 후에는 배경색이 변경됩니다. 어떻게 그 작업을 취소 할 수 있습니까? 이 방법을 다르게 구현해야합니까?

답변

0

귀하의 실제 문제는 당신이 removeCallback은 당신이 그것을 전에 게시 된 하나와 일치하지 않도록, 해결책이있다, Runnable를 모든 onTouch의 새 인스턴스를 만들 것입니다 :

메소드 범위 밖에서 Runnable을 선언하고 그것을 down에서만 초기화하십시오.

또한이 문제가 발생할 수 있으므로 UP으로 ACTION_CANCEL을 추가했습니다.

 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

그래, 알아 냈어. 왜 내가이 문제를 겪고 있는지 정확하게 파악 했으므로이 대답에 대한 신뢰를 표시합니다. 나는 그것을 알아 냈다. 그러나 나는 또한 안드로이드가 제공하는 CountDownTimer 클래스를 발견했다. 우리의 솔루션은 모두 작동하지만 나 자신을 더 잘 설명해야합니다. 좋은 직업과 감사 :) –

0

반복으로 7000을 사용하는 대신 더 작은 간격을 수행하고 대신 시간차를 수행 할 수 있으므로 처리기에서 해당 차이가 7000ms를 초과하는지 확인해야합니다. 조건이 충족되면 작업을 수행합니다. 잘하면 당신의 질문을 제대로 이해했습니다.

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

이 경우 어떻게해야할까요? – DWndrer

0

알아 냈습니다. 모두의 도움에 감사드립니다. 그러나 최선의 해결책이라고 생각되는 것을 알아 냈습니다. OnTouchListener 외부에서 CountDownTimer 객체를 만들었습니다. MotionEven.ACTION_UP에서 타이머를 취소했습니다. 그것은 다른 사람이 도움이된다면 여기에 코드입니다 :

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

원하는대로 내 대답을 확인하십시오 –