Подтвердить что ты не робот

Непрерывно увеличивайте целочисленное значение при нажатии кнопки

Я новичок в Android, поэтому извините, если на вопрос легко ответить. У меня есть две кнопки, кнопка уменьшения и увеличения, а посреди них - TextView, который отображает значение.

Когда я нажимаю кнопку уменьшения, значение в TextView уменьшается и увеличивается, когда я нажимаю кнопку увеличения, никаких проблем с этим, я получил эту работу, но проблема в том, что значение только увеличивается/уменьшается на 1 на один клик, То, что я пытаюсь добиться, заключается в том, что, когда я постоянно нажимаю кнопку (например, кнопку увеличения), значение также непрерывно увеличивается и останавливается только при отпускании кнопки увеличения.

Это возможно? Если да, можете ли вы показать пример кода или ссылки о том, как его реализовать? Спасибо!

Вот мой 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>

и вот моя 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);
            }
        });

    }
}
4b9b3361

Ответ 1

Для этого вам понадобится поток, который будет обновлять целочисленное значение, когда вы долго нажимаете на кнопку.

Создайте обработчик в своей деятельности:

private Handler repeatUpdateHandler = new Handler();

И 2 vars, которые будут указывать: увеличивается ли это или уменьшается? Только один набор за раз.

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

И текущее значение числа

public int mValue;

И класс, который будет работать в другом потоке:

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

Добавьте кнопку длинного нажатия на кнопку:

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

В приведенном выше случае кнопка является инкрементальной. Создайте еще одну кнопку, которая установит mAutoDecrement в true.

И декремент() будет функцией, которая будет устанавливать вашу переменную типа int следующим образом:

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

Вы указываете прирост. Oh и REP_DELAY - статическая переменная int, равная 50.

Я вижу, что это выдержка из Jeffrey Cole с открытым исходным кодом NumberPicker, доступная по адресу http://www.technologichron.net/ Должна быть добавлена ​​правильная атрибуция автора.

Ответ 2

Мой способ увеличить значение при длительном нажатии - использовать таймер, используемый для периодической проверки, если кнопка все еще нажата, и чем увеличивает значение, в противном случае отменяет таймер. Для обновления пользовательского интерфейса используйте 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;
        }
    });

Handler:

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

Я опаздываю, чтобы ответить на этот вопрос, но это может помочь любому, кто ищет лучший ответ.

Я создал класс CounterHandler и его безумно прост в использовании для достижения вышеупомянутых функций непрерывного счетчика.

Вы можете найти класс в следующем примере с примером "как использовать". https://gist.github.com/nomanr/d142f4ccaf55ceba22e7f7122b55b9b6

Пример кода

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

Вот и все.:)

Ответ 4

Кажется, что нет идеального решения этого вопроса, и всегда будут некоторые сложности.

Это моя попытка, которая включает в себя ответ Wiktor, но дает целый MainActivity, который вы можете вырезать/вставить.

В моем примере, сложная часть - это onLongClickListener, и насколько она глубока и сколько существует уровней анонимных классов.

Однако, с другой стороны, простота состоит в том, что все включено в один относительно короткий класс (MainActivity), и существует только один основной блок кода - onLongClickListener - который определяется только один раз, и очень ясно, где " код действия:

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


}

Ответ 5

Просто хочу поделиться своим собственным решением, которое сработало для меня очень хорошо.

Сначала создайте обработчик в своей активности

private Handler mHandler = new Handler();

Затем создайте runnables, которые будут увеличивать/уменьшать и отображать ваш номер. Здесь мы проверим, находится ли ваша кнопка все еще в нажатом состоянии и увеличиваем ее, а затем повторно запустим исполняемый файл, если он есть.

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 state through our handler. The delay of 100ms can be changed as needed.
        }
    }
}

Наконец, используйте его в нашей кнопке onLongClickListener

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

Вот оно!


Еще один способ сделать это - объявить как обработчик, так и работоспособный внутри самого OnLongClickListener, хотя я сам не уверен, является ли это хорошей практикой.

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

При выполнении этого непрерывного приращения я бы предложил увеличить значение приращения после определенного времени/числа приращений. Например. Если значение number_of_increment меньше 10, мы увеличиваем на 1. В противном случае мы увеличиваем на 3.

Ответ 6

Хотя принятый ответ является полностью правильным, его можно немного упростить.

По сути, мы можем оптимизировать две вещи:

  • Нам не нужен OnTouchListener.
  • Мы можем создать исполняемый объект только один раз вместо создания нескольких объектов.

Так что это моя версия:

// global variables
Handler handler = new Handler();
Runnable runnable;

increaseView.setOnLongClickListener(new View.OnLongClickListener() {

    @Override
    public boolean onLongClick(View v) {

        runnable = new Runnable() {
            @Override
            public void run() {
                if (!increaseView.isPressed()) return;
                increaseValue();
                handler.postDelayed(runnable, DELAY);
            }
        };

        handler.postDelayed(runnable, DELAY);
        return true;

    }

});

Здесь работающий объект используется повторно. И когда представление больше не нажимается, оно перестает вызывать себя.

Вид или кнопку уменьшения можно определить аналогичным образом.