Extend Button OnClick - android

I am trying to add specific behaviour to Button's onClick, so when they are clicked they have the custom behaviour on top of the specific action for each button.
I have recently started developing for Android and have little experience on the inner quirks of events and UI classes.
WHat I tried, the buttom performs the custom behaviour I write in the extended class, but then doesn't perform the onClick action I assigned to the button specifically.
This is the custom Button I'm trying to do.
public class CooldownButton extends Button implements View.OnClickListener
{
Timer cooldown;
public CooldownButton(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public CooldownButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CooldownButton(Context context)
{
super(context);
}
#Override
public void onClick(View v)
{
cooldown= new Timer();
cooldown.schedule(cooldownRun(),0,500);
setEnabled(false);
//performClick();
}
private TimerTask cooldownRun()
{
return new TimerTask()
{
#Override
public void run()
{
cooldown.cancel();
cooldown.purge();
setEnabled(true);
}
};
}
}
Then I use it on xml layouts like this:
<CooldownButton android:id="#+id/btnNext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onBtnNextClick" />
OnBtnNextClick is never called.
public void onBtnNextClick(View v)
{
if(v.getId() == R.id.btnNext)
{
//Do something
}
}

From what I am seeing you are disabling the button setEnabled(false); and then you want to perform some action on a next click onBtnNextClick(View v). You cannot click a button a second time if it has been disabled when it was first clicked.

I found a solution after following one of the comments indications.
It is not exactly the way I wanted to solve the issue but it gets close.
I scrapped the idea of making the click behaviour in a java class.
Instead I write a click listener in the MainActivity and then set the listener to all buttons I want to have this special click behaviour.
Button nextButton = (Button) layout.findViewById(R.id.btnNext);
nextButton.setOnClickListener(buttonClickListener);
The listener is as follows:
public View.OnClickListener buttonClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
final Button btn = (Button) v;
btn.setEnabled(false);
new Thread(new Runnable() {
#Override
public void run() {
try {Thread.sleep(1000); }
catch (InterruptedException e) {e.printStackTrace();}
MainActivity.this.runOnUiThread(new Runnable()
{
#Override
public void run(){ btn.setEnabled(true); }
});
}
}).start();
switch (v.getId()) {
case R.id.btnNext:
doSomething();
break;
//case R.id.foobar:
//break;
}
}
};

Related

how to find id of layout in a Bitmap Button java source that I made

I made a Bitmap button that has an animation effect on a layout
but it cannot find the id of the layout and it says it indicates Null point
Here is my source below
public class BitmapButton extends Button{
public BitmapButton(Context context) {
super(context);
init();
}
public BitmapButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
setBackgroundResource(R.drawable.background_selector);
setOnClickListener(new OnClickListener() {
boolean selected=true;
Animation anim;
LinearLayout layout_search = (LinearLayout)findViewById(R.id.layout_search);
#Override
public void onClick(View v) {
if(selected) {
setSelected(true);
anim = AnimationUtils.loadAnimation(getContext(), R.anim.translate_down);
***layout_search.startAnimation(anim);***
layout_search.setVisibility(View.VISIBLE);
selected =!selected;
}
else{
setSelected(false);
anim = AnimationUtils.loadAnimation(getContext(), R.anim.translate_up);
layout_search.startAnimation(anim);
layout_search.setVisibility(View.GONE);
selected =!selected;
}
}
});
}
}
=========================================================================
layout_search.startAnimation(anim);
from here it gets wrong saying
java.lang.NullPointerException: Attempt to invoke virtual method void android.widget.LinearLayout.startAnimation(android.view.animation.Animation) on a null object reference
I know findViewById method in Button Class is different from the one in the MainActivity but I just dont know then, how I can find the LinearLayout linear_search?? with this problem I can make the anim effection on this button.
plz let me know...
public class BitmapButton extends Button{
public BitmapButton(Context context) {
super(context);
init();
}
public BitmapButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
setBackgroundResource(R.drawable.background_selector);
setOnClickListener(new OnClickListener() {
boolean selected=true;
Animation anim;
// _____________ just commented out this line ______________
// LinearLayout layout_search = (LinearLayout)v.findViewById(R.id.layout_search);
#Override
public void onClick(View v) {
// i simply add this line here and add view v before findViewById
LinearLayout layout_search = (LinearLayout)v.findViewById(R.id.layout_search);
if(selected) {
setSelected(true);
anim = AnimationUtils.loadAnimation(getContext(), R.anim.translate_down);
***layout_search.startAnimation(anim);***
layout_search.setVisibility(View.VISIBLE);
selected =!selected;
}
else{
setSelected(false);
anim = AnimationUtils.loadAnimation(getContext(), R.anim.translate_up);
layout_search.startAnimation(anim);
layout_search.setVisibility(View.GONE);
selected =!selected;
}
}
});
}
}
LinearLayout layout_search = (LinearLayout)findViewById(R.id.layout_search);
From documentation:
Look for a child view with the given id. If this view has the given id, return this view.
You trying to search layout inside button. Try to use getParent().findViewById
if you want to start animation on parent of button.

Android-Prevent dismissal of dropdown in AutoCompleteTextView after item selection

Even though I'm setting the setOnItemClickListener on the AutoCompleteTextView and performing some custom operations in it, once that method is done, the list dismisses and prints out the object.toString in the editbox.
I want to prevent dismissal of the dropdown on item select and would also like it to not replace the edit box. How can I achieve this ?
I also want to implement the same i used below code to implement it.
Create a custom class and extend AutoCompleteTextView.
Override dismissDropDown() method and remove the super call from it.
Will work for you.
public class CustomAutoComplete extends AutoCompleteTextView {
public NoSelectionAutoComplete(Context context) {
super(context);
}
public NoSelectionAutoComplete(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NoSelectionAutoComplete(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void replaceText(CharSequence text) {
}
#Override
public void dismissDropDown() {
}
}
I added an onClickListener to the entire custom row layout that I was using for the dropdown adapter. This way whenever the row is clicked, my row onClickListener is invoked and the default one for the dropdown is not.
First Question - Prevent dropdown dismissal:
Solved below.
Second Question - Prevent text replacement: (For others interested)
You can extend AutoCompleteTextView and override
protected void replaceText(CharSequence text) {}
to do nothing.
As others mentioned, overriding performCompletion() won't help here.
well at least it seems like they are planning to add this in near future.
/**
* Sets whether the drop-down should remain visible as long as there is there is
* {#link #enoughToFilter()}. This is useful if an unknown number of results are expected
* to show up in the adapter sometime in the future.
*
* The drop-down will occupy the entire screen below {#link #getDropDownAnchor} regardless
* of the size or content of the list. {#link #getDropDownBackground()} will fill any space
* that is not used by the list.
*
* #param dropDownAlwaysVisible Whether to keep the drop-down visible.
*
* #hide Pending API council approval
*/
public void setDropDownAlwaysVisible(boolean dropDownAlwaysVisible) {
mPopup.setDropDownAlwaysVisible(dropDownAlwaysVisible);
}
edit,new answer:
this worked for me but it closes for a sec,and opens again.
class task extends TimerTask {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
autoComplete.showDropDown();
}
});
}
};
autoComplete.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
new Timer().schedule(new task(),0, 10);
}
});
Overriding replaceText without calling super works fine (prevents entering suggested text into AutoCompleteTextView), but overriding dismissDropDown causes not-dismissing dropdown not only when item clicked, but also when onBackPressed, touched outside dialog etc...
I've ended with NOT using setOnItemClickListener method from AutoCompleteTextView at all. I'm creating custom onClick in my custom ArrayAdapter and set it for all Views returned by getView method
View.OnClickListener onClick=null;
public void setOnItemClickListener(View.OnClickListener onClick) {
this.onClick=onClick;
/*this.onClick=new View.OnClickListener(){
#Override
public void onClick(View v) {
if(v.getTag()==null)
return;
Integer position = (Integer) v.getTag();
Toast.makeText(v.getContext(), "position: "+postion, Toast.LENGTH_SHORT).show();
}
});*/
}
#NonNull
#Override
public View getView(int position, View convertView, #NonNull ViewGroup parent) {
... call super/inflate convertView and do your stuff here
setCustomOnClick(convertView, position);
return convertView;
}
private void setCustomOnClick(final View view, final int position){
view.setTag(position);
view.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
if(onClick==null)
return;
// inside called onClick method v.getTag() will return pressed position
onClick.onClick(v);
}
});
}
in fact setting onClick for whole view will cover "original" always-dismissing and always-replacing-text onClick (not called at all then). Remember about adding custom graphic representation, when pressed (ripple/selector are shown when "original" onClick called only)
I've needed also always-visible functionality, because my autocomplete must always show first position (functional), even when there is no suggestions (if present then shown below on positions 1+)
public class AlwaysVisibleAutoCompleteTextView extends AppCompatAutoCompleteTextView {
private boolean showAlways=true;
public AlwaysVisibleAutoCompleteTextView(Context context) {
super(context);
}
public AlwaysVisibleAutoCompleteTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AlwaysVisibleAutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setShowAlways(boolean showAlways) {
this.showAlways = showAlways;
}
#Override
public boolean enoughToFilter() {
return showAlways || super.enoughToFilter();
}
#Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
showDropDownIfFocused();
}
private void showDropDownIfFocused() {
if (enoughToFilter() && isFocused() && getWindowVisibility() == View.VISIBLE)
showDropDown();
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
showDropDownIfFocused();
}
}
when AlwaysVisibleAutoCompleteTextView is focused, but dropdown dismissed and user press view again, then dropdown is not showing, because focus state not changing (onFocusChanged not called), so
autoComplete.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP)
autoComplete.showDropDown();
return false;
}
});
If you aren't planning using setOnTouchListener for your AutoCompleteTextView for any other purpose, then OnTouchListener may be set inside AlwaysVisibleAutoCompleteTextView class (in every constructor)

TimePickerDialog with Neutral button

I have a TimePickerDialog preference with a "TimePreference" class which extends DialogPreference:
public class TimePreference extends DialogPreference{
...
private TimePicker picker=null;
...
public TimePreference(Context ctxt, AttributeSet attrs){
super(ctxt, attrs);
setPositiveButtonText(android.R.string.ok);
setNegativeButtonText(android.R.string.cancel);
}
#Override
protected View onCreateDialogView(){
picker=new TimePicker(getContext());
return(picker);
}
...
}
I would like to add a third button, which will set the preference to the current time and close the dialog, like this:
The question is, is there some way of doing this using TimePickers or should I make a custom AlertDialog?
Thanks for your answers! I will show you how I finally managed it, just in case someone wants to do the same.
First, I have a layout file good_timedialog.xml which looks like I wanted:
Then I have a TimePreference class:
public class TimePreference extends DialogPreference{
private final static String lTag="CustomTimeDialog";
private TimePicker picker;
protected TimeObj lastTime;
public TimePreference(Context ctxt,AttributeSet atrs) {
super(ctxt,atrs);
setDialogLayoutResource(R.layout.good_timedialog); // this loads the layout
setPositiveButtonText("");
setNegativeButtonText(""); // hide default buttons
setDialogTitle(ctxt.getString(R.string.selectTimeTimePrefTitle));
}
#Override
protected void onBindDialogView(View v){
super.onBindDialogView(v);
v.findViewById(R.id.butCancel).setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
Log.d(lTag,"cancel clicked");
getDialog().dismiss();
}
});
v.findViewById(R.id.butNow).setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
Log.d(lTag,"now clicked");
saveToSP(true);
getDialog().dismiss();
}
});
v.findViewById(R.id.butOK).setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
Log.d(lTag,"ok clicked");
saveToSP(false);
getDialog().dismiss();
}
});
picker = (TimePicker) v.findViewById(R.id.timePicker);
if (picker!=null) {
picker.setCurrentHour(lastTime.hr);
picker.setCurrentMinute(lastTime.min);
} else { // if it is null
Log.w(lTag,"var picker is null!");
}
}
void saveToSP(boolean now){
if (now) lastTime = new TimeObj(); // make it the current time
else {
lastTime.hr = picker.getCurrentHour();
lastTime.min = picker.getCurrentMinute();
}
setSummary(lastTime.giveString()); // update Summary like hh:mm 16:28
int time = lastTime.giveMinutes(); // 10:30am will be 630 minutes
// save to sharedprefs
if(callChangeListener(time)){
persistInt(time);
if(getEditor().commit()) Log.d(lTag,"Successfully saved changes");
else Log.w(lTag,"Did NOT save changes");
}
}
//... more ...
}
And at the perferences.xml file, I can use <com.example.TimePreference android:key="test"/>
Dialog supports three buttons by default - positive, negative and cancel. You could rename them as per your wish and handle them accordingly.

Android radio button uncheck

The application is a step sequencer application with 16 radio groups with 8 buttons in each group. It works perfectly except once a group has a button selected I cant turn it off unless I use the clear button I have created to clear all radiogroups. What I would like to add is some code that says when a selected radio button is selected again it simply turns off like a toggle. I tried using toggles but then other issues arose with that method. Below are two attempts but both simply stops me using the button
final RadioGroup radioGroup1 = (RadioGroup) findViewById(R.id.RadioGroup1);
RadioButton D1 = (RadioButton) findViewById(R.id.RadioButtonD1);
Button D1 = (Button) findViewById(R.id.RadioButtonD1);
D1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick (View v){
PdBase.sendFloat("D1", 74);
int selectedTypeId = radioGroup1.getCheckedRadioButtonId();
RadioButton D1 = (RadioButton) findViewById(selectedTypeId);
if (D1 != null) // This will be null if none of the radio buttons are selected
radioGroup1.clearCheck();
PdBase.sendFloat("D1", 0);
}
});
RadioButton lC1 = (RadioButton) findViewById(R.id.RadioButtonlowC1);
lC1.setOnClickListener(new View.OnClickListener() {
public void onClick (View v) {
int selectedTypeId = radioGroup1.getCheckedRadioButtonId();
RadioButton lC1 = (RadioButton) findViewById(R.id.RadioButtonlowC1);
if (selectedTypeId == -1) {
PdBase.sendFloat("lC1", 72);
}
else if (selectedTypeId == R.id.RadioButtonlowC1) {
radioGroup1.clearCheck();
PdBase.sendFloat("lC1", 0);
}
}
});
I recently had the same need - to have a radio group where the selected item could be deselected by tapping it again. I found that I couldn't accomplish that using listeners but I was able to do it using a custom RadioButton, like so...
public class ToggleableRadioButton extends RadioButton {
// Implement necessary constructors
#Override
public void toggle() {
if(isChecked()) {
if(getParent() instanceof RadioGroup) {
((RadioGroup)getParent()).clearCheck();
}
} else {
setChecked(true);
}
}
}
Notice that the button is toggled in different ways depending on its current state - i.e., calling setChecked(true) on the button vs. calling clearCheck() on the group. If setChecked() is used in both cases, a button that was just deselected cannot be immediately re-selected - the logic in RadioGroup seems to immediately deselect it.
To use this button, just replace your <RadioButton> tags with <your.package.ToggleableRadioButton> in your layout XML.
I just used the answer from #spaaarky21
and my full code look like this and it is working fine!
Java Class
public class ToggleableRadioButton extends RadioButton {
public ToggleableRadioButton(Context context) {
super(context);
}
public ToggleableRadioButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ToggleableRadioButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ToggleableRadioButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
public void toggle() {
if(isChecked()) {
if(getParent() instanceof RadioGroup) {
((RadioGroup)getParent()).clearCheck();
}
} else {
setChecked(true);
}
}
}
And for the XML layout
<com.smart_dent.adapters.ToggleableRadioButton android:id="#+id/tejido_blando_perfil_convexo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/tejido_blando_convexo_label" />
In this case you just need to change the package, I this is easy to find, it is just at the top of the Java Class Flie (if you created it from Android Studio)
It actually can be done with listeners but with an OnTouchListener, which will trigger before the button's state has changed, instead of the usual OnClickListener. The following works for me:
View.OnTouchListener radioButtonOnTouchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (((RadioButton) v).isChecked()) {
// If the button was already checked, uncheck them all
radioGroup.clearCheck();
// Prevent the system from re-checking it
return true;
}
return false;
}
};
radioButton1.setOnTouchListener(radioButtonOnTouchListener);
radioButton2.setOnTouchListener(radioButtonOnTouchListener);
Where radioGroup is the parent of radioButton1 and radioButton2
Edit from #spaaarky21 answer
#Override
public void toggle() {
if (isChecked()) {
if (getParent() instanceof RadioGroup) {
((RadioGroup) getParent()).clearCheck();
}
// add else here when a single radioButton without radioGroup
else {
setChecked(false);
}
} else {
setChecked(true);
}
}
This is also doing the job:
public final class ToggleAbleRadioButton extends AppCompatRadioButton {
public ToggleAbleRadioButton(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
#Override public void toggle() {
setChecked(!isChecked());
}
}
You can use a boolean to toggle the button on and off.
Add a boolean somewhere in your code:
var radioButton1IsSelected = false
Then setup the onClickListener for the button:
radioButton1.setOnClickListener {
radioButton1IsSelected = !radioButton1IsSelected
radioButton1.isChecked = radioButton1IsSelected
}

noob: android button

I have two button b1 and b2 .If button b1 is pressed then perform a query q1 else if button b2 is pressed then perform an another query q2.
if(b1_click)
{
mCursor=//query
}
else if(b2_click)
{
mCursor=//query
}
Please tell me how can i implement this.How to implement b1_click method or any inbuilt method which tell that button is pressed.I tried
Cursor c;
c=//querys
if(b1.isPressed())
{
next.setOnClickListener
(
new View.OnClickListener()
{
#Override public void onClick(View v) {
c=db.getData1(); (getData1 method return cursor)
}
}
);
}
tv.append(c.getString(column_number) (tv=TextView)
"Same as above for b2"
It is saying that cursor (c) should be final
Help?
First of all I would recommend going through some tutorials Hello Android and you could also follow the code and samples in Common Tasks and How to do them in Android.
If you would read this carefully you would know that is very simple, something like this:
public class MyActiviy extends Activity implements OnClickListener{
protected void onCreate(Bundle savedInstance){
super.onCreate(savedInstance);
setContentView(R.layout.myLayout);
findViewById(R.id.Button1).setOnClickListener(this);
findViewById(R.id.Button2).setOnClickListener(this);
//more code...
}
public void onClick(View v){
switch(v.getId()){
case R.id.Button1:
//Button1 pressedd...do stuff
break;
case R.id.Button2:
//Button2 pressed...do some other stuff
break;
default:
break;
}
}
}
Try creating your OnClickListeners as private classes:
private class Button1ClickedListener implements OnClickListener {
public void onClick( View v ) {
//Do what needs to be done when button 1 is clicked.
}
}
private class Button2ClickedListener implements OnClickListener {
public void onClick( View v ) {
//Do what needs to be done when button 2 is clicked.
}
}
Then you set the onClick-listeners:
b1.setOnClickListener( new Button1ClickedListener() );
b2.setOnClickListener( new Button1ClickedListener() );
If you need the OnClickListeners to be able to use the cursor, you just need to declare it as a private field in the parent class of the OnClickListeners.

Categories

Resources