So I am making an app with 3 buttons. Currently I have the following .xml file that makes them have rounded off edges and be the colour red. Now I want to to make them so if one is selected then that button turns green while the other two remain, or turn back to red. How could I go about doing this? Do I have to make another .xml file?
Here is my drawable .xml file for the buttons:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" android:padding="10dp">
<!--red colour.-->
<solid android:color="#FF0000"/>
<corners
android:bottomRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp"/>
<stroke android:width="2px" android:color="#000000"/>
</shape>
Use a selector as follows:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- green state -->
<item
android:drawable="#drawable/button_selected"
android:state_selected="true"></item>
<!-- green state -->
<item
android:drawable="#drawable/button_pressed"
android:state_pressed="true"></item>
<!-- red state -->
<item
android:drawable="#drawable/button_disabled"></item>
</selector>
Then, you should call this selector like:
<Button
...
android:background="#drawable/my_selector" />
And create each drawable.xml (as your example for the red button) for every state: button_selected, button_pressed and button_disabled.
You can also remain the state by using onTouchListener like:
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// change the color
return true;
case MotionEvent.ACTION_UP:
// intitial color
return true;
default:
return false;
}
}
});
However, it's better to use a Selector and a background, this use less resource.
UPDATE:
You can use a setBackgroundResource method to remain and change the background state of clicked button as follows:
// 1st clicklistener method
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
v.setBackgroundResource(R.drawable.green_drawable);
button2.setBackgroundResource(R.drawable.selector_drawable);
}
}
// 2nd clicklistener method
button2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
v.setBackgroundResource(R.drawable.green_drawable);
button1.setBackgroundResource(R.drawable.selector_drawable);
}
}
Not tested but it should work.
Related
I am working on a project where a button should stay pressed when the user touches or taps on it. I have done it successfully using:
button.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
button.setPressed(true);
return true;
}
});
Now, my problem is: when I pull down the status bar or minimize the app using home/back button (from navigation bar), the button becomes unpressed.
I have tried to solve this using:
onSaveInstanceState(Bundle savedInstanceState)
to save the pressed state of the button, but it didn't work.
Now, how can I solve this problem?
I have found two solutions to this (I personally like the second one).
Solution 1
Firstly, I have used onResume() and a flag variable to save the button's state when user minimizes the app.
Secondly, I have used onWindowFocusChanged() and that same flag variable to save the button's state when user pulls down the status bar.
Demo code:
public class MainActivity extends AppCompatActivity {
Button button;
int flag=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
button.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
button.setPressed(true);
flag=1;
return true;
}
});
}
#Override
public void onResume() {
super.onResume();
if(flag==1){
button.setPressed(true);
}else{
button.setPressed(false);
}
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
// handle when the user pull down the notification bar where
// (hasFocus will ='false') & if the user pushed the
// notification bar back to the top, then (hasFocus will ='true')
super.onWindowFocusChanged(hasFocus);
if (!hasFocus) {
Log.i("Tag", "Notification bar is pulled down");
}
else {
Log.i("Tag", "Notification bar is pushed up");
if(flag==1){
button.setPressed(true);
}else{
button.setPressed(false);
}
}
}
}
Solution 2:
Firstly, I have created a file in drawable named button_bg.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="false" android:state_focused="false"
android:state_pressed="false"
android:drawable="#drawable/button_disabled">
</item>
<item android:state_selected="true"
android:drawable="#drawable/button_default">
</item>
<item android:state_focused="true"
android:drawable="#drawable/button_default">
</item>
<item android:state_pressed="true"
android:drawable="#drawable/button_default">
</item>
</selector>
Create two files in drawable (button_disabled.xml & button_default.xml) which are used in button_bg.xml.
button_disabled.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#b6b7b5" />
<padding
android:bottom="7dp"
android:left="7dp"
android:right="7dp"
android:top="7dp" />
<stroke
android:width="2dp"
android:color="#050303" />
<corners android:radius="15dp" />
</shape>
button_default.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="#6FA803"/>
<padding
android:bottom="7dp"
android:left="7dp"
android:right="7dp"
android:top="7dp" />
<stroke
android:width="2dp"
android:color="#050303" />
<corners android:radius="15dp" />
</shape>
Then, I have added this button_bg.xml file as a background of my button:
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/button_bg"
android:text="Button" />
Lastly, I have used setOnClickListener() and View.setSelected() to select the button view and stay pressed:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.setSelected(true);
}
});
The reason I like the second solution is: I don't need to handle the button's state manually. So, when I will be working on with several buttons, the second solution will be more handy.
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/vopressed" /> //light blue
<item android:state_selected="true" android:drawable="#drawable/voselected" /> //blue
<item android:drawable="#drawable/vo" /> //black
</selector>
XML:
<ImageButton
android:layout_width="0dp"
android:layout_weight="0.2"
android:layout_height="wrap_content"
app:srcCompat="#drawable/vo_selector"
android:id="#+id/ibS"
android:background="#android:color/transparent" />
I am trying to change to light blue on click and dark blue after.
ibS.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ibS.setPressed(true);
Toast.makeText(MainActivity.this, "clicked", Toast.LENGTH_LONG).show();
}
});
How can I make it so when I click on it, it stays on the pressed/selected state and the drawable change from black to blue and when I click on it again it unpresses/unselects itself and change back to black.
You can try with selected state of the drawable ::
ibS.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ibS.setPressed(true);
Toast.makeText(MainActivity.this, "clicked", Toast.LENGTH_LONG).show();
}});
Change the line ibS.setPressed(true); to ibS.setSelected(!ibs.isSelected());
So, it will change the drawble of image to the selected_state image define in the drawable the putting the state selected too..on clicking again..it will revert the last state...
Try this..
Use button instead of Image Button as in that case you will be required with two image assets.
Use drawable :
Button unpressed state :
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="2dp" android:color="#color/colorPrimary" />
<padding android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
<solid android:color="#color/colorPrimary" />
</shape>
Button pressed state :
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="2dp" android:color="#color/colorPrimaryDark" />
<padding android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
<solid android:color="#color/colorPrimaryDark" />
</shape>
Now set this above drawable when in need.
When you remove your finger from the button, the pressed state will always reset to false, so you can't use that state.
You should track your state directly by declaring member variable
private boolean isPressed = false;
Then you set the background of the image button directly when the button clicked
ibS.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
isPressed = !isPressed;
if (isPressed) {
ibS.setBackgroundColor(R.color.your_blue_color);
//use code below if you want to use drawable background
//ibS.setBackgroundResource(R.drawable.background_pressed);
} else {
ibS.setBackgroundColor(R.color.your_black_color);
//use code below if you want to use drawable background
//ibS.setBackgroundResource(R.drawable.background_normal);
}
}
});
ibS.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ibS.setBackground(ContextCompat.getDrawable(your Context,R.drawable.voselected));
Toast.makeText(MainActivity.this, "clicked", Toast.LENGTH_LONG).show();
}
});
How are you? I am new at Android programming. so far I have run a single app on my mobile phone using 4.1 API 16.
My question is when releasing a click event the button image in the following code should be restored to previous state.
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
x = x + 1;
edittext.setText("" + x);
button.setBackgroundResource(R.drawable.buttonpressed1);
}
});
you can also use drawable touch states. an example showing color change on press:
in your button xml use android:background="#drawable/touchstates"
and touchstates.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<stroke android:color="#cc0099CC" android:width="1dip" />
<solid android:color="#660099CC" />
</shape>
</item>
</selector>
For normal performance you must use selector like background property of Button view
put all of this files to folder drawable
selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/bg_pressed" android:state_pressed="true" />
<item android:drawable="#drawable/br_unpressed" />
</selector>
bg_pressed.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<stroke
android:width="#dimen/circle_padding"
android:color="#android:color/transparent" />
<solid android:color="#android:color/white" />
</shape>
bg_unpressed.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<stroke
android:width="#dimen/circle_padding"
android:color="#android:color/transparent" />
<solid android:color="#android:color/black" />
</shape>
and in layout set button background android:background="#drawable/selector"
There is a full solution for you:
ImageButton guessButton;
guessButton = (ImageButton) findViewById(R.id.Knorr_Game_Guess_Button);
guessButton.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
v.setBackgroundResource(R.drawable.ic_picture1);
}
else if (event.getAction() == MotionEvent.ACTION_UP)
{
v.setBackgroundResource(R.drawable.ic_picture2);
}
return false;
}
});
It works:)
If you want to capture the release of a button, you need to use OnTouchListener
Here is an example:
yourButton.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
//What happens when preessed
} else if (event.getAction() == MotionEvent.ACTION_UP) {
//What happens when released }
}
};
Hope this helped!
You need to use a selector. The selector needs to be a drawable file which is assigned to the background of your button. An example of a selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- focused -->
<item
android:state_focused="true"
android:drawable="#drawable/rounded_button_focused"
/>
<!--pressed -->
<item
android:state_pressed="true"
android:drawable="#drawable/rounded_button_pressed"
/>
<item
android:drawable="#drawable/rounded_button_unfocused"/>
</selector>
The selector will basically assign the correct background depending on the state of your button. If the button is pressed then it will assign the file "rounded_button_pressed" to the background of the button. The rounded_button_pressed is another drawable file for example:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#color/WhiteSmoke"
android:endColor="#color/LightGrey"
android:angle="270"/>
<stroke
android:width="2dp"
android:color="#color/CornflowerBlue" />
<corners
android:radius="4dp"
/>
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
Hope it solves your problem
I'm creating a rollover effect with regards to a button background and its text. I've been able to create the rollover effect for the background such that when button is in a pressed or focused state then the background is changed from black to yellow. Below is how I did this:
in my fragment:
btnLogin.setBackgroundResource(R.drawable.btn_login);
here's the background resource i.e. btn_login.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/btn_loginrollover" /> <!-- pressed -->
<item android:state_focused="true"
android:drawable="#drawable/btn_loginrollover" /> <!-- focused -->
<item android:drawable="#drawable/btn_logindefault" /> <!-- default -->
</selector>
btn_logindeault.xml:
<?xml version="1.0" encoding="utf-8"?>
<!-- res/drawable/rounded_edittext.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
android:padding="10dp">
<solid android:color="#000000"/>
<corners
android:bottomRightRadius="4dp"
android:bottomLeftRadius="4dp"
android:topLeftRadius="4dp"
android:topRightRadius="4dp"/>
<gradient
android:startColor="#000000"
android:centerColor="#000000"
android:endColor="#FFFFFF"
android:angle="90"/>
</shape>
btn_loginrollover.xml:
<?xml version="1.0" encoding="utf-8"?>
<!-- res/drawable/rounded_edittext.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
android:padding="10dp">
<solid android:color="#FFCC00"/>
<corners
android:bottomRightRadius="3dp"
android:bottomLeftRadius="3dp"
android:topLeftRadius="3dp"
android:topRightRadius="3dp"/>
</shape>
I would like to do the same thing for the button text such that when the button is in a pressed or focused state then the text is changed from black to yellow.
the when the button is but with regards to it's text. Below is my unsuccessful attempt to do this using the setOnFocusChangeListener:
btnLogin.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
btnLogin.setTextColor(Color.BLACK);
} else {
btnLogin.setTextColor(Color.parseColor("#FFCC00"));
}
}
});
I also tried using the button's setOnTouchListener to monitor the event and the change the text color accordingly but this was also unsuccessful:
btnLogin.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (hasFocus) {
btnLogin.setTextColor(Color.BLACK);
} else {
btnLogin.setTextColor(Color.parseColor("#FFCC00"));
}
}
});
Any ideas as to how I could solve my issue?
Thanks.
hey try this code i have tested and working fine when i press button its change color to yellow and when you release its back to black color :)
btnLogin.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
btnLogin.setTextColor(Color.parseColor("#FFCC00"));
break;
case MotionEvent.ACTION_UP:
btnLogin.setTextColor(Color.BLACK);
break;
}
return true;
}
});
yesterday I noticed the possibility to integrate Fragments in older API Levels through the Compatibility package, but thats not really essential for the question. :)
I have a Button with an OnClickListener
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
doSomething();
button.setPressed(true);
}
});
Because of the actual clicking, it is shown as pressed and after releasing the click, the button state is not pressed and stays that way.
Is there a simple way that keeps the button state pressed after releasing?
First thing I can think of would be some sort of timer, but that seems unreasonable.
Just to note this is because Android is changing the setPressed both before and after your onClickEvent, so changing it yourself has no effect. Another way to get around this is to use the onTouchEvent.
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// show interest in events resulting from ACTION_DOWN
if (event.getAction() == MotionEvent.ACTION_DOWN) return true;
// don't handle event unless its ACTION_UP so "doSomething()" only runs once.
if (event.getAction() != MotionEvent.ACTION_UP) return false;
doSomething();
button.setPressed(true);
return true;
}
});
Use ToggleButton instead of Button.
<ToggleButton
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#drawable/topping_selector"
android:checked="false"
android:textOff="Topping2"
android:textOn="Topping2" />
topping_selector.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true"
android:drawable="#drawable/btn_topping_on" />
<item android:state_checked="false"
android:drawable="#drawable/btn_topping_off" />
</selector>
You can keep the button states in xml file under drawable folder, then used as background for button.
For example:
android:background="#drawable/buttonstate"
buttonstate.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/back_focused" />
<item android:drawable="#drawable/back" /> <!-- default -->
</selector>
Better solution:
In xml file:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_activated="true">
<bitmap android:src="#drawable/image_selected"/>
</item>
<item>
<bitmap android:src="#drawable/image_not_selected"/>
</item>
</selector>
And in java:
#Override
public void onClick(View v) {
v.setActivated(!v.isActivated());
}
You can use android.os.Handler class. Ugly, but works also:
final Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
doSomething();
new Handler().post(new Runnable() {
#Override
public void run() {
button.setPressed(true);
}
});
}
});
Another solution is to extend Button and override setPressed(boolean pressed) method so you can handle platform calls from the onClickEvent using a flag, for example changing the boolean pressed parameter depending on your needs.
public class MyButton extends Button {
boolean isSelected = false; //this is your flag
#Override
public void setPressed(boolean pressed) {
if(isSelected) {
//here you change the parameter so it stays pressed
super.setPressed(true);
return;
}
super.setPressed(pressed);
}
public void setIsSelected(boolean selected) {
this.isSelected = selected;
}
public MyButton(Context context) {
super(context);
}
}
This is the solution I used, It also works on android 7.0 at the moment.
YourActivity.java
public void onStandbyStart(String message) {
startStandbyBtn.setActivated(true);
}
public void onBackOnline(String message) {
startStandbyBtn.setActivated(false);
}
YourActivityLayout
<Button
...
style="#style/generic_btn_style"
... />
values/styles.xml
<style name="generic_btn_style" parent="#android:style/Widget.Button">
<item name="android:gravity">center_vertical|center_horizontal</item>
<item name="android:background">#drawable/generic_btn</item>
<item name="android:textColor">#color/selector_white_black</item>
<item name="android:focusable">true</item>
<item name="android:clickable">true</item>
</style>
drawable/generic_btn.xml
This selector chooses the button background. I use the pressed as the activated.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/generic_btn_disabled" android:state_enabled="false" />
<item android:drawable="#drawable/generic_btn_pressed" android:state_enabled="true" android:state_pressed="true" />
<item android:drawable="#drawable/generic_btn_pressed" android:state_activated="true" />
<item android:drawable="#drawable/generic_btn_focused" android:state_enabled="true" android:state_focused="true" />
<item android:drawable="#drawable/generic_btn_enabled" android:state_enabled="true" />
</selector>
color/selector_black_white
Here I set the text color. In my case, I need to pick the textcolor black when pressed.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#fff" android:state_pressed="true" /> <!-- pressed -->
<item android:color="#fff" android:state_activated="true" /> <!-- pressed -->
<item android:color="#000" /> <!-- default -->
</selector>