Disabled button loses pressed state when touched - android

I'm generating a number of buttons programmatically (some to increase a value while others to decrease a value) that I disable when the value they adjust either reaches a maximum or minimum. (i.e. The 'increase' button is disabled when the maximum is reached while the 'decrease' button is disabled when the minimum is reached.) In addition to disabling, I'm also setting the button state to 'pressed' in order to visually indicate that the limit value has been reached and the button no longer functions.
My button onClickListener for the 'increase' buttons look like this:
increase.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// do some stuff
// here I enable the corresponding 'decrease' button because once you increase you can then decrease
setEnabled(decrease, true);
// if the maximum value is obtained, I disable the 'increase' button because you can't go higher
if (value == maximum) {
setEnabled(increase, false);
}
}
});
The corresponding 'decrease' onClickListeners are similar.
Because these button are changing their own state, I need to use a Handler to adjust Button.setEnabled() and Button.setPressed() after a small delay, so that the user's finger doesn't get in the way (see https://stackoverflow.com/a/28788780/852795). Here is the setEnabled(final Button b, final boolean set) method that is used above:
private void setEnabled(final Button b, final boolean set) {
Handler refresh = new Handler(Looper.getMainLooper());
refresh.postDelayed(new Runnable() {
#Override
public void run() {
b.setEnabled(set);
b.setPressed(!set);
}
}, 250); // delayed post required to make pressed button accept setPressed()
}
Everything works great, with one small exception: once a user presses the 'increase' button enough times to reach the maximum the button will be disabled and the 'pressed' state will be set to true, however, if it's then pressed one more time, the 'pressed' state will be turned off. Functionally, the button is disabled. I know this because the onClickHandler is not invoked. Why then is my button losing it's 'pressed' state? How can I stop this from happening?
Update: Looking at https://stackoverflow.com/a/8693444/852795 I tried plugging into the onTouchListener() in order to 'intercept' the touch that's turning off the pressed state. However, this, too, is not invoked because, I would imagine, the button is disabled.

One way to handle this would be to use a StateListDrawable as the background of the button and set the Disabled state to use the same drawable as the Pressed state. This way you could avoid having to set the Pressed state in code.
ie
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#drawable/btn_pressed" /> <!-- pressed -->
<item android:state_enabled="false" android:drawable="#drawable/btn_pressed"/> <!-- disabled (same as pressed) -->
<item android:state_enabled="true" android:drawable="#drawable/btn_normal"/>
</selector>

Related

Android's touch event doesn't work

I'm trying to do a simple imageview with a colored background that when pressed change the color and at the end of the touch if it is outside the image area then it would return to the original color or else start another activity (like a button); so i decided to implement an onTouchListener in my activity using a kotlin lambda.
This is the code:
imageview.setOnTouchListener{ view: View, event: MotionEvent ->
val rect = Rect(view.left, view.top, view.right, view.bottom)
when(event.action){
MotionEvent.ACTION_DOWN->{
view.setBackgroundColor(dark_color)
}
MotionEvent.ACTION_UP-> {
if (rect.contains(event.x.toInt(), event.y.toInt()))
startActivity(Intent(this, NewActivity::class.java)
else{
view.setBackgroundColor(normal_color)
}
}
}
true
}
And it works fine but while i was testing it i saw that the new activity was starting else if the touch is out of the image area, so i used the Log function to report the cordinates of the touch and i noticed that the cordinates (when MotionEvent.ACTION_UP was triggered) where different from the point that i was touching on the screen.
Is it possible that the system is bugged ?
(p.s. i tried also on the emulator and i had the same result and I can't use xml selectors)
Thanks for help!
The only thing you need to do is to create a selector. You set the selector as a background to your ImageView. So the selector manage the colour automatically (when the image is pressed or not). Then you set a listener on your ImageView to manage the click event. If the user moves his finger out of the ImageView area, the listener will NOT be triggered (it's automatically managed).
In your Java code
imageView.setOnClickListener(new View.OnClickListener {
public void onClick(...){
// Start the Activity
}
});
in your XML
<ImageView
android:background="#drawable/my_selector"
//...
my_selector.xml (must be in the drawable folder)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/default_pressed" android:state_pressed="true" />
<item android:color="#color/default_not_pressed" />
</selector>

How do I programmatically check an Android radio button with ripple animation?

tl;dr: When the user clicks an unrelated text view, I want a radio button to be selected with a ripple animation. performClick doesn't do this. What should I be doing instead?
I have a radio button with both a label and a longer description.
The general structure of my layout is this:
<RadioGroup>
<RadioButton
id="#+id/officialBusinessRadio"
text="Official business" />
<TextView
id="#+id/officialBusinessCaption"
text="This operates under a ..." />
<!-- ... -->
</RadioGroup>
I've added an OnClickListener to the text view so that tapping on the caption selects the radio button:
officialBusinessCaption.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
officialBusinessRadio.performClick();
}
});
When I tap on the radio button itself or on its own text ("Official Business"), the radio button animates to selected and a ripple ink effect occurs. When I top on the caption text (and performClick is called), the radio button still animates to selected, but no ripple occurs.
Is there a more correct way to get this effect? That is, is there a better way to forward a click on the caption text view to the radio button? If not, is there a straightforward way to trigger the ripple effect on the radio button programmatically?
I would prefer against setting all the text using a string resource for the following reasons:
I intend on styling the label and the caption differently.
I want the radio vertically center aligned with the first line of text.
I've hit this problem by population RadioButtons in a RecyclerView. All of them are set to isClickable = false because I override their selection according to another rule, but the way to trigger the selection to true is doing:
Kotlin:
radioButton.post {
radioButton.isChecked = true
}
Java:
radioButton.post(new Runnable() {
#Override
public void run() {
radioButton.setChecked(true);
}
})
before, I was doing setChecked(true) only and it wouldn't work.

Flash image on button click over the button

As I am working on keyboard, we know on default keyboard on any android device when we click any button larger image is flashed above button, I don't know exactly this effect, ut I have tried using below code.
Button which is clicked in my Keyboard.xml:
<Button android:id="#+id/xBack"
android:background="#drawable/back_high"/>
Above back_high is my xml file.
back_high.xml file is,
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/back_click"
android:state_pressed="true" />
<item android:drawable="#drawable/back"
android:state_focused="true" />
<item android:drawable="#drawable/back" />
</selector>
Its working successfully, but image is flashed at same place where I clicked, but I need this image is displayed on above button, as happening on android default keyboard.
your setting the background of that specific button, so if you want it to appear above the button make sure you use a frame layout as the overall layout of the keyboard and then have a single extra imageview that you switch location and resource when you click on a button. you won't need the selector anymore.
Frame layout's will let you put multiple views on top of each other.
This Link :
Why not make this programmatically and not in UI mode?
There are several, depending on what kind of flashing you mean.
You can, for example, use alpha animation and start it as your button first appears. And when the user clicks button, in your OnClickListener just do clearAnimation().
Example:
public void onCreate(Bundle savedInstanceState) {
final Animation animation = new AlphaAnimation(1, 0); // Change alpha from fully visible to invisible
animation.setDuration(500); // duration - half a second
animation.setInterpolator(new LinearInterpolator()); // do not alter animation rate
animation.setRepeatCount(Animation.INFINITE); // Repeat animation infinitely
animation.setRepeatMode(Animation.REVERSE); // Reverse animation at the end so the button will fade back in
final Button btn = (Button) findViewById(R.id.your_btn);
btn.startAnimation(animation);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(final View view) {
view.clearAnimation();
}
});
}
Also This Answer.

How to detect touch events on disabled checkbox in android

I have a layout with couple checkboxes. When one checkbox gets checked the others are set to CHECKED=true and ENABLED=false. Now I want the user to be able to tap on any of that disabled checkboxes and if he does that, one is set to enabled and checked and all the other are disabled.
The onTouchListener as well as the onClickListener doesn't seem to be called when the checkbox is set to ENABLED=false. Can anyone help?
You can not receive events on a disabled checkbox. If you put the disabled checkbox on a layout like FrameLayout, you can receive the events when you click on the layout but not in the disabled checkbox. The best way if you want to capture events on a disabled checkbox is to simulate a disabled checkbox simply, and capture a long click event to activate again, for example.
What I have done is a checkbox with white text color but beginning with grey text color and unchecked, with a boolean stopper variable which you check before on every onCheckedChanged method. Checkbox is never checked unless you change the boolean stopper variable. You can press on checkbox many times as you want and nothing happens. It only appears to be disabled but when you press a long click you unblock the boolean stopper variable and change the grey text color checkbox to white like a normal checkbox. You can change the stopper variable when you want and "disabling it again"
In color.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="white">#FFFFFF</color>
<color name="grey">#808080</color>
</resources>
In main.xml:
<CheckBox
android:id="#+id/checkbox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:text="text" />
In the main.java code, onCreate method:
//define a boolean stopper variable to check on event
boolean chkActivated = false;
checkbox = (CheckBox) findViewById(R.id.checkbox1);
checkbox.setTextColor(getResources().getColorStateList(R.color.grey));
checkbox.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(chkActivated){
if (isChecked) {
//Do everthing you want when checked
}else{
//Do everthing you want when unchecked
}
}else{
checkbox.setChecked(false);
Toast.makeText(Activity.this, "It is disabled. to activate press long click"), Toast.LENGTH_SHORT).show();
}
}
});
checkbox.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
chkActivated = true;
checkbox.setTextColor(getResources().getColorStateList(R.color.white));
checkbox.setChecked(true);
return true;
}
});
Hope this helps you
Usually the behavior for a situation like that is a question-mark in Android. One thing you may be able to do is to put the CheckBox from something descended from ViewGroup (One of the many layouts like FrameLayout, for example) and use setOnClickListener on it.

Automatically alter button background and text appearance when pressed (like iOS)?

In iOS, if I set a button's background to an image, when I press the button, the whole content of the button (including the text) will be shadowed. Can I achieve the same effect in Android, or do I have to use different images for different states? Also, even if I use different images for different states, how do I make the text also shadowed? A dirty way is to set a OnClickListener to the button and programatically shadow the text when pressed, but are there any other ways?
I´ve been trying to find a solution for this for a while now but couldn´t find anything so I came up with a pretty neat solution which works on all image buttons. Just like iOS.
Create a Black, 10% transparent image and save it as PNG. I call it button_pressed.png. You can use this image, http://img84.imageshack.us/img84/7924/buttonpressed.png
Create a drawable called something relevant, I call it "button_pressed_layout.xml"
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android=" http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#drawable/button_pressed" />
</selector>
Now put your button image in the LinearLayout and then the Button inside the LinearLayout. In the Button use button_pressed_layout.xml as background.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/button_image">
<Button
android:id="#+id/myButtonId"
android:text="#string/Continue"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/button_pressed_layout"
android:textColor="#FFF"
android:textSize="16dp" >
</Button>
</LinearLayout>
That´s it!
To get a pressed-state without creating a 2nd button image, I created an OnTouchListener to change the button's alpha. This is not the most beautiful pressed state, but gives an effective automatic behavior.
public class PressedStateOnTouchListener implements OnTouchListener
{
PressedStateOnTouchListener( float alphaNormal )
{
mAlphaNormal = alphaNormal;
}
public boolean onTouch( View theView, MotionEvent motionEvent )
{
switch( motionEvent.getAction() ) {
case MotionEvent.ACTION_DOWN:
theView.setAlpha( mAlphaNormal / 2.0f );
break;
case MotionEvent.ACTION_UP:
theView.setAlpha( mAlphaNormal );
break;
}
// return false because I still want this to bubble off into an onClick
return false;
}
private float mAlphaNormal;
}
In your Activity, apply this listener to each button:
Button theButton = (Button)findViewById( R.id.my_button_id );
theButton.setOnTouchListener( new PressedStateOnTouchListener( theButton.getAlpha() ));
In order to give the button itself different effects, I believe you need to use custom images, as seen here and, in less detail here As for the text, this post looks like it would do the trick for the shadow

Categories

Resources