按下按钮时连续增加整数值

Posted

技术标签:

【中文标题】按下按钮时连续增加整数值【英文标题】:Continuously increase integer value as the button is pressed 【发布时间】:2011-12-17 19:40:39 【问题描述】:

我是 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_
    android:layout_
    android:gravity="center" >

    <RelativeLayout
        android:layout_
        android:layout_
        android:gravity="center_horizontal" >

        <Button android:id="@+id/button1"
            android:layout_
            android:layout_
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:text="&lt;" />

        <TextView android:id="@+id/textView1"
            android:layout_
            android:layout_
            android:layout_alignBottom="@+id/button1"
            android:layout_toRightOf="@+id/button1"
            android:gravity="center"
            android:text="45" />

        <Button android:id="@+id/button2"
            android:layout_
            android:layout_
            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);
            
        );

    

【问题讨论】:

【参考方案1】:

为此,您需要一个线程来在您长按按钮时更新整数值。

在您的活动中创建一个处理程序:

private Handler repeatUpdateHandler = new Handler();

还有 2 个变量将说明:是递增还是递减?一次只能设置一组。

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 的按钮。

而 decrement() 将是一个函数,它将像这样设置您的实例 int 变量:

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

你计算出增量。哦,REP_DELAY 是一个静态 int 变量,设置为 50。

我看到这是 Jeffrey Cole 的开源 NumberPicker 的摘录,地址为 http://www.technologichron.net/ 必须添加正确的作者署名。

【讨论】:

我按照您的指示创建了increment() 函数并声明了REP_DELAY,没有错误但是当我单击增量按钮时,值会增加,但即使我释放它,值仍然是增加并且不会停止。减少按钮也是如此。我错过了什么吗? 抱歉,忘记添加 onTouchListener,它将清除增量标志(减量相同) - 请参阅更新的代码。 添加了 onTouchListener 用于递增和递减,现在它可以工作了。谢谢!不胜感激! :) 感谢您的帮助。当我需要为多个值做这个递增/递减的事情时,有什么想法吗?它会重复很多次。 你不需要另一个线程只需使用handler post runnables...从handler 上的touch up 上删除runnable callbacks 【参考方案2】:

虽然接受的答案是完全正确的,但可以稍微简化一下。

基本上,我们可以优化两件事:

我们不需要 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;

    

);

这里可运行对象被重用。并且当视图不再被按下时,它会停止调用自己。

可以用类似的方式定义缩小视图或按钮。

【讨论】:

【参考方案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】:

我在长按时增加值的方法是使用 Timer 来定期检查按钮是否仍被按下,而不是增加值,否则取消计时器。要更新 UI,请使用 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;
        
    );

处理程序:

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

【讨论】:

【参考方案5】:

只想分享我自己的解决方案,对我来说效果很好。

首先,在您的活动中创建一个处理程序

private Handler mHandler = new Handler();

然后,创建可递增/递减并显示您的数字的可运行文件。在这里,我们将检查您的按钮是否仍处于按下状态并递增,如果是则重新运行可运行对象。

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.
        
    

最后,在我们按钮的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】:

这个问题似乎没有完美的解决方案,总会涉及一些复杂性。

这是我的尝试,它结合了 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());
    



【讨论】:

【参考方案7】:

导入 java.awt.; 导入 java.awt.event.; 公共类 LabelNumber 扩展 Frame 实现 ActionListener

    Button badd,bsub;
    TextField t1;
    
void display()

    setTitle("Label number change");
    setSize(400,500);
    setLayout(new FlowLayout());
    setVisible(true);

    badd=new Button("+");
    t1=new TextField("0",6);

    bsub= new Button("-");
    add(bsub);add(t1);add(badd);
  

badd.addActionListener(this);
bsub.addActionListener(this);

addWindowListener(new WindowAdapter()

    public void windowClosing(WindowEvent e)
    
        System.exit(0);
    

);

public void actionPerformed(ActionEvent e)
    
    int count=0,add=0,sub,n1,n2;
        count=Integer.parseInt(t1.getText());
            
    if(e.getSource()==badd)
    
        if(count<10)
        
            count=count+1;
            t1.setText(""+count);
        
        else
        
            t1.setText("limit:10");
                       
    
    
    if(e.getSource()==bsub)
    
        if(count<10)
        
            count=count-1;
            t1.setText(""+count);
        
        else
        
            t1.setText("limit:10");
                       
    



public static void main(String args[])

    LabelNumber obj =new  LabelNumber();
    obj.display();


【讨论】:

请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助,质量更高,更有可能吸引投票。【参考方案8】:

对于 kotlin 用户

    myButton.setOnLongClickListener 
        val handler = Handler(Looper.myLooper()!!)
        val runnable : Runnable = object : Runnable 
            val number = 0
            override fun run() 
                handler.removeCallbacks(this)
                if (myButton.isPressed) 
                    val newNumber= number + 1
                    textView.text = "$newNumber Items"
                    handler.postDelayed(this, 100)
                
            
        
        handler.postDelayed(runnable,0)
        true
    

【讨论】:

【参考方案9】:

初始化并调用方法

int speed = 0;
 button = findViewById(R.id.button);
    button.setOnTouchListener((v, event) -> 
        if (event.getAction() == MotionEvent.ACTION_DOWN) 
            v.setPressed(true);
                    increment();
         else if (event.getAction() == MotionEvent.ACTION_UP) 
            v.setPressed(false);
            speed = 0;
         
        return true;
    );

这是增加方法

    public void increment() 
        new Handler().postDelayed(() -> 
            Toast.makeText(FrequencyActivity.this, String.valueOf(speed), Toast.LENGTH_SHORT).show();
            if (button.isPressed()) 
                speed += 1;
                increment();
            
        , 200); //200 ms for fast incrementing
    

【讨论】:

【参考方案10】:

Kotlin 和 Coroutines 用户的版本(如果您愿意,可以将 GlobalScope 替换为任何其他范围):

    var job: Job? = null

    viewClickable.setOnClickListener 
        // single click
    

    viewClickable.setOnLongClickListener 
        if (job == null || !job!!.isActive) 
            job = GlobalScope.launch(Dispatchers.Main.immediate) 
                while (it.isPressed) 
                    // long press
                    delay(100)
                
            
        
        true
    

【讨论】:

【参考方案11】:

我创建的最佳和简单的解决方案,看看它对我有用

public void increment() 
    new Handler().postDelayed(new Runnable() 
        @Override
        public void run() 
            check_amount = check_amount + 100;// increment by 100
            tv_balance.setText("" + check_amount); // show continues incrementing value
            if (check_amount != 5000) 
                increment();
            
        
    , 1); //1 ms for fast incrementing

【讨论】:

以上是关于按下按钮时连续增加整数值的主要内容,如果未能解决你的问题,请参考以下文章

按下其他连续按钮时如何取消选择按钮?

jquery css在每次按下按钮时连续旋转90度

【Android开发】如何 使得 android长按按钮=多次按下按钮

为什么按下按钮时我的物体不能连续旋转?

按下按钮时增加枚举值

尝试按下按钮将精灵的 zRotation 增加 1 度时旋转不正确