I have a Button, TextView(number) and an ImageView. Every time I press the button the number will increment. It will increment a lot faster when I hold the button.
I want to show an image at a specific number using ImageView at the same time making the button visible to INVISIBLE for a while to stop the increment.
The problem: If I press the button one click at a time then the below code functions well but as I hold down the button, the image appears for a very short while and continue with the numbers. And although the button is set invisible for 5 seconds, the numbers still increases(as the button is still hold).
MAIN CLASS
public class MainActivity extends AppCompatActivity {
Button button;
TextView textView;
ImageView imageView;
int i=0;
#SuppressLint("ClickableViewAccessibility")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView=findViewById(R.id.imageView);
textView=findViewById(R.id.textView);
button = findViewById(R.id.button);
button.setOnTouchListener(new RepeatListener(400, 100, new View.OnClickListener() {
#Override
public void onClick(View view) {
setText();
setImage();
}
}));
}
public void setText(){
imageView.setVisibility(View.INVISIBLE);
textView.setText(""+i);
i++;
}
public void setImage(){
if(i==10){
imageView.setImageResource(R.drawable.kitten);
imageView.setVisibility(View.VISIBLE);
buttonInvi();
}
}
public void buttonInvi(){
button.setVisibility(View.INVISIBLE);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
button.setVisibility(View.VISIBLE);
}
}, 5000); // where 1000 is equal to 1 sec (1 * 1000)
}
}
RepeatListener CLASS
public class RepeatListener implements OnTouchListener {
private Handler handler = new Handler();
private int initialInterval;
private final int normalInterval;
private final OnClickListener clickListener;
private View touchedView;
private Runnable handlerRunnable = new Runnable() {
#Override
public void run() {
if(touchedView.isEnabled()) {
handler.postDelayed(this, normalInterval);
clickListener.onClick(touchedView);
} else {
// if the view was disabled by the clickListener, remove the callback
handler.removeCallbacks(handlerRunnable);
touchedView.setPressed(false);
touchedView = null;
}
}
};
public RepeatListener(int initialInterval, int normalInterval,
OnClickListener clickListener) {
if (clickListener == null)
throw new IllegalArgumentException("null runnable");
if (initialInterval < 0 || normalInterval < 0)
throw new IllegalArgumentException("negative interval");
this.initialInterval = initialInterval;
this.normalInterval = normalInterval;
this.clickListener = clickListener;
}
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
handler.removeCallbacks(handlerRunnable);
handler.postDelayed(handlerRunnable, initialInterval);
touchedView = view;
touchedView.setPressed(true);
clickListener.onClick(view);
return true;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
handler.removeCallbacks(handlerRunnable);
touchedView.setPressed(false);
touchedView = null;
return true;
}
return false;
}
}
How about checking the visibility before increasing the counter
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
if(view.getVisibility() == View.VISIBLE){
handler.removeCallbacks(handlerRunnable);
handler.postDelayed(handlerRunnable, initialInterval);
touchedView = view;
touchedView.setPressed(true);
clickListener.onClick(view);
}
return true;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if(view.getVisibility() == View.VISIBLE){
handler.removeCallbacks(handlerRunnable);
touchedView.setPressed(false);
touchedView = null;
}
return true;
}
return false;
}
Try this line
button.setVisibility(View.GONE);
instead of
button.setVisibility(View.INVISIBLE);
Just set your listener to null when you reach a specific number and show imageview and make button invisible then after 5 seconds again set your listener and make button visible
Related
I'm trying to get an AlertDialog to appear if my counter is above 10.
I have tried using the TextView variable peopleCount in the if statement but it does not work too. I know using TextView will not work but I need to know if there is a workaround.
private TextView peopleCount;
private ImageView plusOne;
private ImageView minusOne;
private ImageView reset;
private int counter;
private View.OnClickListener clickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.ivPlusOne :
plusCounter();
break;
case R.id.ivMinusOne :
minusCounter();
break;
case R.id.ivReset :
initCounter();
break;
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_people);
peopleCount = (TextView)findViewById(R.id.tvPeopleCount);
plusOne = (ImageView)findViewById(R.id.ivPlusOne);
plusOne.setOnClickListener(clickListener);
minusOne = (ImageView)findViewById(R.id.ivMinusOne);
minusOne.setOnClickListener(clickListener);
reset = (ImageView)findViewById(R.id.ivReset);
reset.setOnClickListener(clickListener);
initCounter();
if( counter > 10) {
AlertDialog.Builder peopleAlert = new AlertDialog.Builder(PeopleActivity.this);
peopleAlert.setCancelable(false);
peopleAlert.setTitle("People Count High");
peopleAlert.setMessage("Please check and replenish inventory");
peopleAlert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogPeople, int which) {
dialogPeople.cancel();
}
});
peopleAlert.show();
}
private void initCounter(){
counter = 0;
peopleCount.setText(counter + "");
}
private void plusCounter(){
counter++;
peopleCount.setText(counter + "");
}
private void minusCounter(){
counter--;
peopleCount.setText(counter + "");
}
I expected the AlertDialog to appear when counter reached 11 but nothing happens.
OnCreate only runs once, You need to move the if statement to a function and call it from your plusCounter() and minusCounter() functions.
Attention! This question is not about dynamic loading of items into a very long ListView.
This is about adding PageUP and PageDown buttons to a ListView so that user can touch the button and scroll ListView page by page. Page means all fully and partially visible items on the screen.
I have partially implemented this in the following code, but my problem is that when I have lets say 10 items of approximately same height in the listview and 7 of them fit into the first page, then when I press PgDown button, user expects that item 8 to be on top of the screen (next page), but because there are only 10 items, ListView scrolls to the bottom of the list and because there is no extra scroll space I have item number 4 on top.
What is the best solution in this situation?
Should I add one item to the end of the list which will make the last page the height of the screen or there are any better options?
Here is my code:
public class cPaginatedListViewHelper {
Activity m_parentActivity;
private ListView mList;
//controls
private LinearLayout m_PagingLL;
//buttons
private ImageButton m_btnPrevPage;
private ImageButton m_btnNextPage;
private ImageButton m_btnExitPaginatedMode;
public cPaginatedListViewHelper(ListActivity mParent) {
this.m_parentActivity = mParent;
m_btnPrevPage=(ImageButton) mParent.findViewById(R.id.btnPrevPage);
m_btnNextPage=(ImageButton) mParent.findViewById(R.id.btnNextPage);
m_btnExitPaginatedMode =(ImageButton) mParent.findViewById(R.id.btnClosePage);
if(m_btnPrevPage!=null) {
m_btnPrevPage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showSiblingPage(-1);
}
});
m_btnPrevPage.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
mList.smoothScrollToPosition(0);
return true;
}
}
);
}
if(m_btnNextPage!=null) {
m_btnNextPage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showSiblingPage(1);
}
});
m_btnNextPage.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
mList.smoothScrollToPosition(mList.getCount());
return true;
}
}
);
}
m_btnExitPaginatedMode.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setEnabled(false);
m_PagingLL.setVisibility(View.GONE);
}
});
mList=mParent.getListView();
m_PagingLL = (LinearLayout) mParent.findViewById(R.id.pageControls);
}
public void updateControlsVisibility()
{
ViewTreeObserver observer = mList.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (willMyListScroll()) {
boolean psm = isEnabled();
//enable or disable
m_PagingLL.setVisibility( psm ? View.VISIBLE : View.GONE);
((View)mList).setVerticalScrollbarPosition(psm ? View.SCROLLBAR_POSITION_LEFT: View.SCROLLBAR_POSITION_RIGHT);
}
else
{
m_PagingLL.setVisibility(View.GONE);
((View)mList).setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_RIGHT);
}
}
});
}
private boolean willMyListScroll() {
try {
int pos = mList.getLastVisiblePosition();
if (mList.getChildAt(pos).getBottom() > mList.getHeight()) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
private void showSiblingPage(int shift)
{
if(mList!=null) {
int iScrollPageHeight = mList.getHeight();
mList.scrollListBy(iScrollPageHeight * shift);
}
}
public void setEnabled(boolean psm) {
MyApp.Pref.edit().putBoolean("PSModeEnabled", psm).commit();
}
public boolean isEnabled(){
return MyApp.Pref.getBoolean("PSModeEnabled", false);
}
public void pagedScrollEnableDisable() {
boolean pagingEnabled = isEnabled();
pagingEnabled=!pagingEnabled;
setEnabled(pagingEnabled);
m_PagingLL.setVisibility( pagingEnabled ? View.VISIBLE : View.GONE);
updateControlsVisibility();
}
}
I finished up with using ListView's footer with variable height as shown in the following code:
LayoutInflater inflater = m_parentActivity.getLayoutInflater();
m_footerView = inflater.inflate(R.layout.listview_paged_overscroll, mList, false );
ViewGroup.LayoutParams lp =m_footerView.getLayoutParams();
if(m_tvPageNum!=null) recalcPagination();
if(lp!=null) lp.height = m_extraScrollFooterHeight;
int iFooters = mList.getFooterViewsCount();
if(iFooters==0) mList.addFooterView(m_footerView);
This question already has answers here:
Android - Detect End of Long Press
(4 answers)
Closed 4 years ago.
I would like to detect when a button is not clicked. For instance, in the code above, I would like to replace the ????? with a condition indicating that the imageview is still being clicked and quit the loop as soon as the imageview is not long clicked anymore. Do you have an idea?
imageView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
while(?????)
{
int number =(Integer.parseInt(hours.getText().toString())+1)%24;
String text_number= String.valueOf(number);
if(number>-1 && number<10)
{
text_number="0"+text_number;
}
hours.setText(text_number);
}
return true;
}
});
Use View.OnTouchListener.
Example: https://stackoverflow.com/a/39588668/4586742
You will get onTouch callback with different events.
MotionEvent.ACTION_DOWN: when the user starts pressing the view.
MotionEvent.ACTION_UP: when the user stops pressing the view.
What i get from your question and proposed answer for you.
`
public class Main2Activity extends AppCompatActivity {
private boolean isImageViewBeingClicked = true;
private boolean isLongPressed = false;
private ImageView imageView;
private TextView hours;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
imageView = (ImageView) findViewById(R.id.imageView);
hours = (TextView) findViewById(R.id.textView);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
while (isImageViewBeingClicked) {
int number = (Integer.parseInt(hours.getText().toString()) + 1) % 24;
String text_number = String.valueOf(number);
if (number > -1 && number < 10) {
text_number = "0" + text_number;
}
hours.setText(text_number);
}
}
});
imageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
if (isLongPressed) {
isImageViewBeingClicked = false;
}
}
return false;
}
});
imageView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
isLongPressed = true;
return false;
}
});
}
}
`
I tried to use gridView inside bottomSheetBehavior.
I get my data asynchronize and i call to setAdapter just when the user click on my button.
The problem is that i see flicker of the data. What can i do to kill this flicker?
In my onCreate:
final ViewGroup gridViewContainer = (ViewGroup) findViewById(R.id.bottomSheetContainer);
if (gridViewContainer != null) {
gridView = (GridView) gridViewContainer.findViewById(R.id.actionGridView);
bottomSheetBehavior = BottomSheetBehavior.from(gridViewContainer);
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_EXPANDED:
isBottomSheetQuickActionOpen = true;
gridViewContainer.requestLayout();
break;
case BottomSheetBehavior.STATE_COLLAPSED:
isBottomSheetQuickActionOpen = false;
break;
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
});
public void onBottomBarIconClicked(View v){
switch(v.getId()){
case R.id.right_bottom_action:
if (bottomSheetBehavior != null) {
if (!isBottomSheetQuickActionOpen) {
setActionsForQuickDialog();
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
} else {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
}
break;
}
}
private void setupQuickActionDialog() {
ActionsManager actionManager = ActionsManager.get();
List<WidgetMetaData> list = getMyList();
if (CollectionUtils.isNotEmpty(list)) {
if (gridView != null) {
adapterGridView = new AdapterGridView(ContactDetailsActivity.this, list, contact);
gridView.setAdapter(adapterGridView);
}
}
}
I found a solution that way:
1. Save member of runnable
private final Runnable runnable = new Runnable() {
#Override
public void run() {
if (!isBottomSheetQuickActionOpen) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
} else {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
}
};
Save the main thread:
Handler mainHandler = new Handler(context.getMainLooper());
When button clicked, first create the gridview icons, second use the mainthread to post runnable. If we want to collapse the bottomsheetbehaviour we should remove the runnable from the queue and then just collapse by
setBottomSheetState(BottomSheetBehavior.STATE_COLLAPSED);
The function that changed:
public void onBottomBarIconClicked(View v) {
switch (v.getId()) {
case R.id.open_menu_btn:
if (bottomSheetBehavior != null) {
if (!isBottomSheetQuickActionOpen) {
setActionsForQuickDialog();
mainHandler.post(runnable);
} else {
handler.removeCallbacks(runnable);
collapseBottomSheet();
}
}
break;
}
}
I am having weird problems with Android GridView. I create a 3x4 grid and insert buttons into that grid. I want the background of the button to change when the user clicks that button. And this is working just fine for all buttons except the first one (the one with index 0 - top left). OnClick event listener doesn't fire at all for that button no matter what I do.
Here is the code where I create the view:
public View getView(int position, View convertView, ViewGroup parent) {
Button imageView;
if (convertView == null) { // if it's not recycled, initialize some attributes
Log.w("NOVO", "narejena nova celica");
imageView = new Button(mContext);
imageView.setPadding(8, 8, 8, 8);
} else {
Log.w("STARO", "stara celica");
imageView = (Button) convertView;
}
imageView.setEnabled(true);
int visina = parent.getHeight();
int sirina = parent.getWidth();
float dip = mContext.getResources().getDisplayMetrics().density;
float margin = 10*dip;
int view_height = (int)(visina - 3*margin)/4;
int view_width = (int)(sirina - 2*margin)/3;
int view_dim = 0;
if (view_height <= view_width)
view_dim = view_height;
else
view_dim = view_width;
imageView.setLayoutParams(new GridView.LayoutParams(view_dim, view_dim));
imageView.setId(position);
imageView.setOnClickListener(celice.get(position));
/*imageView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//Toast toast = Toast.makeText(mContext, v.getId() + "bla", Toast.LENGTH_SHORT);
//toast.show();
celice.get(v.getId()).celicaVisible(4000);
}});*/
celice.get(position).id = position;
celice.get(position).setButton(imageView);
return imageView;
}
If I replace
imageView = (Button) convertView;
with
imageView = new Button(mContext);
then the onClick() gets fired but the background still doesn't change. All the other buttons are working as expected.
And here is the custom class "Celica" that takes care of the actual work - changing the background...
public class Celica implements OnClickListener {
public boolean odkrit;
public boolean najden;
public int id;
public Drawable slikca1, slikca2;
public Celica par;
private Timer tim;
public Button but;
public Context con;
static int buttonsVisible = 0;
Celica(Drawable s1, Drawable s2) {
this.slikca1 = s1;
this.slikca2 = s2;
}
void celicaVisible(int millis) {
if (odkrit)
return;
Log.w("TEST", "prizganih " + buttonsVisible);
if (buttonsVisible >= 2)
return;
odkrit = true;
buttonsVisible++;
tim = new Timer();
tim.schedule(new timerDone(), millis);
((Activity)con).runOnUiThread(new Runnable() {
#Override
public void run() {
but.setBackground(slikca2);
}
});
}
void setButton(Button b) {
but = b;
((Activity)con).runOnUiThread(new Runnable() {
#Override
public void run() {
but.setBackground(slikca1);
}
});
}
class timerDone extends TimerTask {
#Override
public void run() {
if (!najden) {
odkrit = false;
((Activity)con).runOnUiThread(new Runnable() {
#Override
public void run() {
but.setBackground(slikca1);
}
});
}
buttonsVisible--;
tim.cancel();
}
}
#Override
public void onClick(View v) {
celicaVisible(4000);
}
}
In Android, ID of any View must be non zero and non negative number. means View ID should be > 0. and there is problem, when you are setting ID to the Button like
imageView.setId(position)
here ID of a button will be zero when position is zero(means first item). may be due to this, First Button's OnClickListener is not getting fired...try setting a ID that is greater than zero to Button and try once...
you can write like
imageView.setId(position+1) to ensure ID > 0
I actually figured it out. Everything works if I use the view that gets provided by the onClick() method instead of saving the actual button at the creation of the Celica object.
So basically adding:
but = (Button) v;
to the onClick() method solved the problem.