web-dev-qa-db-fra.com

Augmenter continuellement la valeur entière lorsque vous appuyez sur le bouton

Je suis nouveau sur Android alors désolé si la question est facile à répondre. J'ai deux boutons, une diminution et une augmentation, et au milieu d'eux un TextView qui affiche une valeur.

Lorsque je clique sur le bouton de diminution, la valeur dans TextView diminue et augmente lorsque je clique sur le bouton d’augmentation, ce n’est pas un problème; cela fonctionne mais le problème est que la valeur n’augmente/diminue de 1 en un seul clic. Ce que j'essaie de faire, c'est que lorsque j'appuie continuellement sur le bouton (le bouton d'augmentation, par exemple), la valeur augmente également de façon continue et ne s'arrête que lorsque je relâche le bouton d'augmentation.

Est-ce possible? Si oui, pouvez-vous montrer un exemple de code ou des références sur la manière de le mettre en œuvre? Merci!

Voici mon main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent"
    Android:gravity="center" >

    <RelativeLayout
        Android:layout_width="fill_parent"
        Android:layout_height="44dp"
        Android:gravity="center_horizontal" >

        <Button Android:id="@+id/button1"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_alignParentLeft="true"
            Android:layout_alignParentTop="true"
            Android:text="&lt;" />

        <TextView Android:id="@+id/textView1"
            Android:layout_width="50dp"
            Android:layout_height="fill_parent"
            Android:layout_alignBottom="@+id/button1"
            Android:layout_toRightOf="@+id/button1"
            Android:gravity="center"
            Android:text="45" />

        <Button Android:id="@+id/button2"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_alignParentTop="true"
            Android:layout_toRightOf="@+id/textView1"
            Android:text="&gt;" />

     </RelativeLayout>   

</RelativeLayout>

et voici mon Main.Java

import Android.app.Activity;
import Android.os.Bundle;
import Android.util.Log;
import Android.view.View;
import Android.view.View.OnClickListener;
import Android.widget.Button;
import Android.widget.TextView;

public class Main extends Activity {

    private Button _decrease;
    private Button _increase;
    private TextView _value;
    private static int _counter = 45;
    private String _stringVal;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        _decrease = (Button) findViewById(R.id.button1);
        _increase = (Button) findViewById(R.id.button2);
        _value = (TextView) findViewById(R.id.textView1);

        _decrease.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                Log.d("src", "Decreasing value...");
                _counter--;
                _stringVal = Integer.toString(_counter);
                _value.setText(_stringVal);
            }
        });

        _increase.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                Log.d("src", "Increasing value...");
                _counter++;
                _stringVal = Integer.toString(_counter);
                _value.setText(_stringVal);
            }
        });

    }
}
26
src

Pour que cela fonctionne, vous avez besoin d’un thread qui mette à jour la valeur entière lorsque vous appuyez longuement sur un bouton.

Créez un gestionnaire dans votre activité:

private Handler repeatUpdateHandler = new Handler();

Et 2 vars qui indiqueront: est-ce incrément ou décrément? Un seul ensemble à la fois.

private boolean mAutoIncrement = false;
private boolean mAutoDecrement = false;

Et la valeur numérique actuelle

public int mValue;

Et une classe qui fonctionnera dans un autre thread:

class RptUpdater implements Runnable {
    public void run() {
        if( mAutoIncrement ){
            increment();
            repeatUpdateHandler.postDelayed( new RptUpdater(), REP_DELAY );
        } else if( mAutoDecrement ){
            decrement();
            repeatUpdateHandler.postDelayed( new RptUpdater(), REP_DELAY );
        }
    }
}

Ajoutez un écouteur de presse long à votre bouton:

mBTIncrement.setOnLongClickListener( 
            new View.OnLongClickListener(){
                public boolean onLongClick(View arg0) {
                    mAutoIncrement = true;
                    repeatUpdateHandler.post( new RptUpdater() );
                    return false;
                }
            }
    );   

mBTIncrement.setOnTouchListener( new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            if( (event.getAction()==MotionEvent.ACTION_UP || event.getAction()==MotionEvent.ACTION_CANCEL) 
                    && mAutoIncrement ){
                mAutoIncrement = false;
            }
            return false;
        }
    });  

Dans le cas ci-dessus, le bouton est l'incrément. Créez un autre bouton qui définira mAutoDecrement sur true.

Et décrrement () sera une fonction, qui définira votre variable d’instance int comme ceci:

public void decrement(){
    mValue--;
    _value.setText( ""+mValue );
}

Vous calculez l'incrément. Oh, et REP_DELAY est une variable statique int définie sur 50.

Je vois que ceci est un extrait de l'open source de Jeffrey Cole, NumberPicker, disponible sur http://www.technologichron.net/ / Il faut ajouter l'attribution de l'auteur.

74
Yar

Je suis en retard pour répondre à cette question, mais cela peut aider tous ceux qui recherchent une meilleure réponse. 

J'ai créé une classe CounterHandler et elle est incroyablement facile à utiliser pour obtenir la fonctionnalité de compteur continu mentionnée ci-dessus. 

Vous pouvez trouver la classe dans Gist suivant avec un exemple "Comment utiliser" . https://Gist.github.com/nomanr/d142f4ccaf55ceba22e7f7122b55b9b6

Exemple de code 

    new CounterHandler.Builder()
            .incrementalView(buttonPlus)
            .decrementalView(buttonMinus)
            .minRange(-50) // cant go any less than -50
            .maxRange(50) // cant go any further than 50
            .isCycle(true) // 49,50,-50,-49 and so on
            .counterDelay(200) // speed of counter
            .counterStep(2)  // steps e.g. 0,2,4,6...
            .listener(this) // to listen counter results and show them in app
            .build();

C'est tout. :)

3
Noman Rafique

Mon moyen d’incrémenter la valeur lors d’un clic long est d’utiliser le minuteur utilisé pour vérifier périodiquement si le bouton est toujours enfoncé et augmenter la valeur, sinon annuler le minuteur. Pour mettre à jour l'interface utilisateur, utilisez Handler.

vh.bttAdd.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {

            final Timer timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                 if(vh.bttAdd.isPressed()) {
                     final int track = ((ChannelAudioTrack) channels.get(vh.getAdapterPosition())).goToNextTrack();
                  updateUI(vh,track);
                 }
                else
                timer.cancel();
            }
            },100,200);

            return true;
        }
    });

Gestionnaire:

private void updateUI(final TrackViewHolder vh, final int track)
 {
new Handler(Looper.getMainLooper()).post(new Runnable() {
                        @Override
                        public void run() {
                                  vh.tvTrackNumber.setText(Integer.toString(track));
                        }
                    }) ;
}
3

Il semble qu'il n'y ait pas de solution parfaite à cette question et qu'il y aura toujours une certaine complexité.

Ceci est ma tentative, qui intègre la réponse de Wiktor, mais donne une MainActivity entière que vous pouvez couper/coller. 

Dans mon exemple, la partie complexe est onLongClickListener, ainsi que sa profondeur et son nombre de niveaux de classes anonymes. 

Cependant, la simplicité réside dans le fait que tout est inclus dans une classe relativement courte (MainActivity) et qu’il n’existe qu’un bloc de code majeur - le onLongClickListener - qui est défini une seule fois et où le action "code est:

package com.example.boober.aalongclickoptimizationunit;

import Android.support.v7.app.AppCompatActivity;
import Android.os.Bundle;
import Android.view.View;
import Android.widget.Button;
import Android.widget.TextView;

import Java.util.Timer;
import Java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    TextView valueDisplay;
    Button minusButton;
    Button plusButton;
    Button[] arrayOfControlButtons;

    Integer currentDisplayValue = 500;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        valueDisplay = findViewById(R.id.value);
        minusButton = findViewById(R.id.minusButton);
        plusButton = findViewById(R.id.plusButton);

        arrayOfControlButtons = new Button[]{plusButton, minusButton}; // this could be a large set of buttons

        updateDisplay(); // initial setting of display

        for (Button b : arrayOfControlButtons) {

            b.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(final View v) {

                    final Timer timer = new Timer();
                    timer.schedule(new TimerTask() {
                        @Override
                        public void run() {
                            if (v.isPressed()) { // important: checking if button still pressed
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        // --------------------------------------------------
                                        // this is code that runs each time the
                                        // long-click timer "goes off."
                                        switch (v.getId()) {

                                            // which button was pressed?
                                            case R.id.plusButton: {
                                                currentDisplayValue = currentDisplayValue + 10;
                                                break;
                                            }

                                            case R.id.minusButton: {
                                                currentDisplayValue = currentDisplayValue - 10;
                                                break;
                                            }
                                        }
                                        updateDisplay();
                                        // --------------------------------------------------
                                    }
                                });
                            } else
                                timer.cancel();
                        }
                    }, 100, 200);
                    // if set to false, then long clicks will propagate into single-clicks
                    // also, and we don't want that.
                    return true;
                }
            });

        }


    }

    // ON-CLICKS (referred to from XML)

    public void minusButtonPressed(View ignored) {
        currentDisplayValue--;
        updateDisplay();
    }

    public void plusButtonPressed(View ignored) {
        currentDisplayValue++;
        updateDisplay();
    }

    // INTERNAL

    private void updateDisplay() {
        valueDisplay.setText(currentDisplayValue.toString());
    }


}
1
Boober Bunz

Je veux juste partager ma propre solution qui a très bien fonctionné pour moi.

Tout d'abord, créez un gestionnaire dans votre activité

private Handler mHandler = new Handler();

Ensuite, créez les runnables qui vont incrémenter/décrémenter et afficher votre numéro. Ici, nous allons vérifier si votre bouton est toujours dans son état enfoncé et incrémenter, puis réexécuter le runnable si c'est le cas.

private Runnable incrementRunnable = new Runnable() {
    @Override
    public void run() {
        mHandler.removeCallbacks(incrementRunnable); // remove our old runnable, though I'm not really sure if this is necessary
        if(IncrementButton.isPressed()) { // check if the button is still in its pressed state
            // increment the counter
            // display the updated value here, if necessary
            mHandler.postDelayed(incrementRunnable, 100); // call for a delayed re-check of the button's state through our handler. The delay of 100ms can be changed as needed.
        }
    }
}

Enfin, utilisez-le dans le bouton onLongClickListener de notre bouton

IncrementButton.setOnLongClickListener(new View.OnLongClickListener() {
    @Override
    public boolean onLongClick(View view) {
        mHandler.postDelayed(incrementRunnable, 0); // initial call for our handler.
        return true;
    }
});

C'est tout!


Une autre façon de procéder consiste à déclarer à la fois le gestionnaire et l’exécutable dans OnLongClickListener lui-même, bien que je ne sois pas sûr que ce soit une bonne pratique.

IncrementButton.setOnLongClickListener(new View.OnLongClickListener() {
    private Handler mHandler = Handler();
    private Runnable incrementRunnable = new Runnable() {
        @Override
        public void run() {
            mHandler.removeCallbacks(incrementRunnable);
            if(IncrementButton.isPressed()) {
                // increment the counter
                // display the updated value here, if necessary
                mHandler.postDelayed(incrementRunnable, 100);
            }
        }
    };

    @Override
    public boolean onLongClick(View view) {
        mHandler.postDelayed(incrementRunnable, 0);
        return true;
    }
});

En faisant cette augmentation continue, je suggère d’augmenter la valeur de l’incrément après un certain temps/nombre d’augmentations . E.g. Si le nombre_incrément effectué est inférieur à 10, nous incrémentons de 1. Sinon, nous incrémentons de 3.

0
Gama the Great