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

时间:2011-10-29 11:12:13

标签: android events button

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

    }
}

10 个答案:

答案 0 :(得分:76)

要使其正常工作,您需要一个线程,当您长按按钮时,该线程将更新整数值。

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

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是一个设置为50的静态int变量。

我看到这是Jeffrey Cole在http://www.technologichron.net/提供的开源NumberPicker的摘录。必须添加正确作者的归属。

答案 1 :(得分: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));
                        }
                    }) ;
}

答案 2 :(得分:3)

我迟到了回答这个问题,但它可以帮助任何寻求更好答案的人。

我创建了一个CounterHandler类,它非常容易使用,以实现上述连续计数器功能。

您可以使用&#34;如何使用&#34;在以下要点中找到该课程。例。 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();

多数民众赞成。 :)

答案 3 :(得分:1)

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

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


}

答案 4 :(得分:1)

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

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

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

    }

});

此处可重用可运行对象。当不再按下视图时,它将停止自动调用。

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

答案 5 :(得分:0)

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

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

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 :(得分:0)

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

}

}

答案 7 :(得分:0)

针对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
    }

答案 8 :(得分:0)

初始化和调用方法

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
    }

答案 9 :(得分:-1)

我创建的最好,最简单的解决方案,请查看它是否对我有用

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
}