按下按钮时连续增加整数值
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="<" />
<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=">" />
</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
【讨论】:
以上是关于按下按钮时连续增加整数值的主要内容,如果未能解决你的问题,请参考以下文章