Skip to content

Instantly share code, notes, and snippets.

@nomanr
Last active November 14, 2023 10:49
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nomanr/d142f4ccaf55ceba22e7f7122b55b9b6 to your computer and use it in GitHub Desktop.
Save nomanr/d142f4ccaf55ceba22e7f7122b55b9b6 to your computer and use it in GitHub Desktop.
A simple Android class that can start continuous counter when pressed and hold on a view.
package noman.counterhelper;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
/**
* Created by Noman on 11/8/2016.
*/
public class CounterExampleActivity extends AppCompatActivity implements CounterHandler.CounterListener{
TextView txtCounter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_counter_example);
Button buttonPlus = (Button) findViewById(R.id.buttonPlus);
Button buttonMinus = (Button) findViewById(R.id.buttonMinus);
txtCounter = (TextView) findViewById(R.id.txtCounter);
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();
}
@Override
public void onIncrement(View view, long number) {
txtCounter.setText(String.valueOf(number));
}
@Override
public void onDecrement(View view, long number) {
txtCounter.setText(String.valueOf(number));
}
}
package noman.counterhelper;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by Noman on 11/8/2016.
*/
public class CounterHandler {
final Handler handler = new Handler();
private View incrementalView;
private View decrementalView;
private long minRange = -1;
private long maxRange = -1;
private long startNumber = 0;
private long counterStep = 1;
private int counterDelay = 50; //millis
private boolean isCycle = false;
private boolean autoIncrement = false;
private boolean autoDecrement = false;
private CounterListener listener;
private Runnable counterRunnable = new Runnable() {
@Override
public void run() {
if (autoIncrement) {
increment();
handler.postDelayed(this, counterDelay);
} else if (autoDecrement) {
decrement();
handler.postDelayed(this, counterDelay);
}
}
};
private CounterHandler(Builder builder) {
incrementalView = builder.incrementalView;
decrementalView = builder.decrementalView;
minRange = builder.minRange;
maxRange = builder.maxRange;
startNumber = builder.startNumber;
counterStep = builder.counterStep;
counterDelay = builder.counterDelay;
isCycle = builder.isCycle;
listener = builder.listener;
initDecrementalView();
initIncrementalView();
if (listener != null) {
listener.onIncrement(incrementalView, startNumber);
listener.onDecrement(decrementalView, startNumber);
}
}
private void initIncrementalView() {
incrementalView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
increment();
}
});
incrementalView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
autoIncrement = true;
handler.postDelayed(counterRunnable, counterDelay);
return false;
}
});
incrementalView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP && autoIncrement) {
autoIncrement = false;
}
return false;
}
});
}
private void initDecrementalView() {
decrementalView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
decrement();
}
});
decrementalView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
autoDecrement = true;
handler.postDelayed(counterRunnable, counterDelay);
return false;
}
});
decrementalView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP && autoDecrement) {
autoDecrement = false;
}
return false;
}
});
}
private void increment() {
long number = startNumber;
if (maxRange != -1) {
if (number + counterStep <= maxRange) {
number += counterStep;
} else if (isCycle) {
number = minRange == -1 ? 0 : minRange;
}
} else {
number += counterStep;
}
if (number != startNumber && listener != null) {
startNumber = number;
listener.onIncrement(incrementalView, startNumber);
}
}
private void decrement() {
long number = startNumber;
if (minRange != -1) {
if (number - counterStep >= minRange) {
number -= counterStep;
} else if (isCycle) {
number = maxRange == -1 ? 0 : maxRange;
}
} else {
number -= counterStep;
}
if (number != startNumber && listener != null) {
startNumber = number;
listener.onDecrement(decrementalView, startNumber);
}
}
public interface CounterListener {
void onIncrement(View view, long number);
void onDecrement(View view, long number);
}
public static final class Builder {
private View incrementalView;
private View decrementalView;
private long minRange=-1;
private long maxRange=-1;
private long startNumber=0;
private long counterStep =1;
private int counterDelay=50;
private boolean isCycle;
private CounterListener listener;
public Builder() {
}
public Builder incrementalView(View val) {
incrementalView = val;
return this;
}
public Builder decrementalView(View val) {
decrementalView = val;
return this;
}
public Builder minRange(long val) {
minRange = val;
return this;
}
public Builder maxRange(long val) {
maxRange = val;
return this;
}
public Builder startNumber(long val) {
startNumber = val;
return this;
}
public Builder counterStep(long val) {
counterStep = val;
return this;
}
public Builder counterDelay(int val) {
counterDelay = val;
return this;
}
public Builder isCycle(boolean val) {
isCycle = val;
return this;
}
public Builder listener(CounterListener val) {
listener = val;
return this;
}
public CounterHandler build() {
return new CounterHandler(this);
}
}
}
@meysam2594
Copy link

hi there !
thanks for your great code,
i use this in my activity and work but when i use in my resyclerview adapter an implement CounterHandler I can't use onIncrement and onDecrement Because i can't call my viewHolder please help me

@Naveen112001
Copy link

Builder in counterExampleactivity.java class is not created

@bernardkaminskiBK
Copy link

Nice work!

@uzairmughal3397
Copy link

nice work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment