1. Mitglieder surfen ohne Werbung auf Android-Hilfe.de! ✔ Jetzt kostenlos Mitglied in unserer Community werden.
  1. no1Ltan, 06.09.2018 #1
    no1Ltan

    no1Ltan Threadstarter Android-Hilfe.de Mitglied

    Hallo,

    ich versuche in dieser kleinen Test-App, die aus nur 1 Activity und 1 TextView besteht, folgendes:
    Beim Klick auf die TextView soll einfach der Wert innerhalb der TextView mit 1 addiert werden.

    Zusätzlich soll es einen Klick-Effekt geben (visuelles Feedback) und es soll verhindert werden, dass ein Doppelklick möglich ist.
    Beim Doppelklick soll also nicht addiert werden und der Klick-Effekt soll auch nicht an sein.

    Habe es hinbekommen, dass der Doppelklick nicht funktioniert und den Klick-Effekt habe ich auch hinbekommen.
    Leider schaffe ich es nicht, den Klick-Effekt kurzzeitig zu deaktivieren.
    Ich dachte, SystemClock.sleep(1000); würde mir da helfen, aber das sorgt einfach nur für eine Verzögerung in der Methode.

    Das ist der Code:
    Code:
    import android.content.res.TypedArray;
    import android.os.SystemClock;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity
    {
        private int count;
        private long mLastClickTime = 0;
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            final TextView textViewCount = findViewById(R.id.text_view_count);
            textViewCount.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) // If second click is within 1 second:
                    {
                        return; // Don't execute code below
                    }
                    mLastClickTime = SystemClock.elapsedRealtime(); // Reset mLastClickTime
                    rippleEffect(); // Add click effect
                    count++; // Increment counter by 1
                    String countText = Integer.toString(count); // Cast int to String
                    textViewCount.setText(countText); // Show String value in TextView
                }
            });
        }
        public void rippleEffect() // Add click effect
        {
            TextView textViewCount = findViewById(R.id.text_view_count); // Link ID with variable
            int[] attrs = new int[]{R.attr.selectableItemBackground};
            TypedArray typedArray = obtainStyledAttributes(attrs);
            int backgroundResource = typedArray.getResourceId(0, 0);
            textViewCount.setBackgroundResource(backgroundResource);
            textViewCount.setClickable(false); // Set clickable to false
            SystemClock.sleep(1000); // Add delay of 1 s - BAD IDEA!
            textViewCount.setClickable(true); // Set clickable to true again
        }
    }
    
    Wie bekomme ich es hin, dass auch der Klick-Effekt aus ist, wenn der Counter nicht hochgezählt wird?

    Bezüglich des Hintergrundes in der TextView ist auch einiges unklar... aber eins nach dem anderen.

    Grüße
     
  2. swa00, 06.09.2018 #2
    swa00

    swa00 Moderator Team-Mitglied

    Hallo,

    unter Android gibt es in dem Sinne kein "Sleep".
    Zeitverzögerungen sollten daher mittels Thread ausgeführt werden -
    So wie du es oben anwendest läuft es nicht frei und du blockierst das UI-System

    Bsp :
    Code:
     Handler handler = new Handler();
                        handler.postDelayed(new Runnable()
                        {
                            @Override
                            public void run()
                            {
                              // Do
                            }                       
                        }, 1000);
    
    Vielmehr würde ich Dir anraten, das Ganze in einem AsyncTask zu betten .
    Du kannst auch einen OnTouchListener verwenden , um einen Doppelclick abzufangen
     
    Zuletzt bearbeitet: 06.09.2018
  3. jogimuc, 06.09.2018 #3
    jogimuc

    jogimuc Erfahrener Benutzer

    Versuche es mal so


    Code:
         if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) // If second click is within 1 second:
                    {
                        mLastClickTime = SystemClock.elapsedRealtime(); // Reset mLastClickTime
                        return; // Don't execute code below
                    }
                    mLastClickTime = SystemClock.elapsedRealtime(); // Reset mLastClickTime
                    rippleEffect(); // Add click effect
                    count++; // Increment counter by 1
                    String countText = Integer.toString(count); // Cast int to String
                    textViewCount.setText(countText); // Show String
                    
                  
    
     
  4. no1Ltan, 07.09.2018 #4
    no1Ltan

    no1Ltan Threadstarter Android-Hilfe.de Mitglied

    Hab's (unsauber) gelöst.
    Die Frage ist, ob es auch bei einer "echten App" funktionieren wird, wenn der Hintergrund
    aus einer SharedPreferences kommt.
    (Da würde dann statt R.color.red eben eine Variable stehen.)

    Code:
    import android.content.res.TypedArray;
    import android.os.Handler;
    import android.os.SystemClock;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity
    {
        private int count;
        private long mLastClickTime = 0;
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            final TextView textViewCount = findViewById(R.id.text_view_count);
            textViewCount.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) // 1 second
                    {
                        textViewCount.setBackgroundResource(R.color.red);
                        return;
                    }
                    mLastClickTime = SystemClock.elapsedRealtime();
                    rippleEffect();
                    count++;
                    String countText = Integer.toString(count);
                    textViewCount.setText(countText);
                }
            });
        }
        public void rippleEffect()
        {
            TextView textViewCount = findViewById(R.id.text_view_count);
            int[] attrs = new int[]{R.attr.selectableItemBackground};
            TypedArray typedArray = obtainStyledAttributes(attrs);
            int backgroundResource = typedArray.getResourceId(0, 0);
            textViewCount.setBackgroundResource(backgroundResource);
        }
    }
    
    In diesem Fall wird der originale Hintergrund der TextView wieder hergestellt,
    falls man innerhalb 1 Sekunde nochmal klickt.

    @jogimuc:
    Habe deinen Code versucht, aber keinen Unterschied gemerkt.
    Trotzdem danke!

    @swa00:
    Also ich hatte es probiert, aber das einzige, was anders war, war der fehlende Klick-Effekt
    beim ersten Klick.
    Kann aber natürlich trotzdem sein, dass ich was falsch gemacht habe.

    Zusätzlich versuchte ich noch die clickable kurzzeitig auf false zu setzen.
    Allerdings wurde die nie wieder auf true gesetzt.

    Code:
    import android.content.res.TypedArray;
    import android.os.Handler;
    import android.os.SystemClock;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity
    {
        private int count;
        private long mLastClickTime = 0;
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            final TextView textViewCount = findViewById(R.id.text_view_count);
            textViewCount.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) // 1 second
                    {
                        return;
                    }
                    mLastClickTime = SystemClock.elapsedRealtime();
                    rippleEffect();
                    count++;
                    String countText = Integer.toString(count);
                    textViewCount.setText(countText);
                }
            });
        }
        public void rippleEffect()
        {
            final TextView textViewCount = findViewById(R.id.text_view_count);
            Handler handler = new Handler();
            handler.postDelayed(new Runnable()
            {
                @Override
                public void run()
                {
                    int[] attrs = new int[]{R.attr.selectableItemBackground};
                    TypedArray typedArray = obtainStyledAttributes(attrs);
                    int backgroundResource = typedArray.getResourceId(0, 0);
                    textViewCount.setBackgroundResource(backgroundResource);
                    textViewCount.setClickable(false);
                }
            }, 1000);
            textViewCount.setClickable(true);
        }
    }
    
    P.S. Die final TextView brauche ich, damit die "innere Klasse" auch drauf zugreifen kann.

    Grüße
     
  5. no1Ltan, 30.10.2018 #5
    no1Ltan

    no1Ltan Threadstarter Android-Hilfe.de Mitglied

    Hallo,
    ist schon etwas länger her, aber ich wollte keinen neuen Thread erstellen.

    Hab mir jetzt angewohnt, viel mehr mit Methoden zu arbeiten, um eine bessere Übersicht zu haben.

    Allerdings schaffe ich es mit diesem "PreventDoubleClick" einfach nicht.
    Wenn ich diesen Codeblock verwende, funktioniert es einwandfrei:

    Code:
        textView1.setOnClickListener(new View.OnClickListener()
        {
            @Override public void onClick(View v)
            {
                if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) // If user already clicked within 1 second:
                {
                    return; // Don't execute code below
                }
                mLastClickTime = SystemClock.elapsedRealtime(); // Reset mLastClickTime
                count++; // Increment count by 1
                moveEffect(textView1); // Start moving animation
            }
        });
    
    Bei diesem funktioniert es aber nicht:
    Code:
        textView1.setOnClickListener(new View.OnClickListener()
        {
            @Override public void onClick(View v)
            {
                preventDoubleClick();
                count++; // Increment count by 1
                moveEffect(textView1); // Start moving animation
            }
        });
    
    public void preventDoubleClick()
    {
      if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) // If user clicks second time within 1 second:
      {
          return; // Don't execute code below
      }
      mLastClickTime = SystemClock.elapsedRealtime(); // Reset mLastClickTime
    }
    

    Dass es nicht funktioniert, ergibt für mich sogar Sinn.
    Soweit ich das einschätzen kann, bezieht sich das return auf die 1 Codezeile innerhalb der Methode.

    Im Beispiel oben bezieht sich das return auf die 3 Codezeilen des onClickListeners.

    Wie müsste ich die Methode schreiben, so dass sie auch für das Beispiel 2 funktioniert?
    Klar könnte ich eine if-Abfrage machen, aber dann wäre es fast wie Beispiel 1.

    Keine große Sache, aber es interessiert mich dennoch.
    Wenn es technisch nicht möglich ist, habe ich wenigstens wieder was dazu gelernt.

    Grüße
     
  6. deek, 30.10.2018 #6
    deek

    deek Android-Experte

    Um den Control Flow einer Methode A zu verlassen die eine andere Methode B gecallt hat bleibt B nur eine Exception. Alternativ halt in B ein boolen zurückgeben und in A checken. Aber wie du sagst sieht es dann aus wie vorher.
    Exception würde ich nicht empfehlen in diesem Fall.
     
  7. jogimuc, 30.10.2018 #7
    jogimuc

    jogimuc Erfahrener Benutzer

    Eine Lösung wäre es mit einen Rückgabewert zu machen.
    Code:
    textView1.setOnClickListener(new View.OnClickListener()
        {
            @Override public void onClick(View v)
            {
                if(!preventDoubleClick()) return;
                count++; // Increment count by 1
                moveEffect(textView1); // Start moving animation
            }
        });
    
    public boolean preventDoubleClick()
    {
      if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) // If user clicks second time within 1 second:
      {
          return false; // Don't execute code below
      }
      mLastClickTime = SystemClock.elapsedRealtime(); // Reset mLastClickTime
      return true;
    }
     
    no1Ltan bedankt sich.
  8. deek, 30.10.2018 #8
    deek

    deek Android-Experte

    Mir fällt noch ne schöne Variante mit Lambdas ein falls du Java 8 Source aktiviert hast.

    Code:
       textView1.setOnClickListener(new View.OnClickListener()  {
           @Override public void onClick(View v)
           {
               executeForSingleClick(() -> {
                  count++; // Increment count by 1
                  moveEffect(textView1); // Start moving animation
               });
           }
       });
    
    public void executeForSingleClick(Runnable callback) {
      if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) // If user clicks second time within 1 second:
      {
         return; // Don't execute code below
      }
      mLastClickTime = SystemClock.elapsedRealtime(); // Reset mLastClickTime
      callback.run();
    }
    
    Auch wenn ich aus den bisherigen Posts von dir rausgelesen habe, dass du wohl kein Fan davon bist.
     
    no1Ltan bedankt sich.
Die Seite wird geladen...
Ähnliche Themen Forum Datum
Benötigte Zugriff ausschalten Android App Entwicklung 07.03.2018
Bild öffnen bei Klick Android App Entwicklung 25.01.2018
Du betrachtest das Thema "Klick-Effekt bei Doppelklick ausschalten?" im Forum "Android App Entwicklung",
  1. Android-Hilfe.de verwendet Cookies um Inhalte zu personalisieren und dir den bestmöglichen Service zu gewährleisten. Wenn du auf der Seite weitersurfst stimmst du der Cookie-Nutzung zu.  Ich stimme zu.