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); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
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