How would I model a follow/unfollow button in Android? Is State List Drawable what I am looking for? How can define the two different states?
This is highly dependant on the visual effect you want to achieve.
First, the basics (I assume you already know this): you need a Button, setOnClickListener() for a listener that toggles the state, and someplace to save this (either a local database, your own server, or whatever).
The easiest, least attractive way, would be to just switch the text on the button whenever the "follow" state changes (with setText() in the click listener).
A possible improvement would be to have different button backgrounds, so that the appearance also changes (say, from a grey star to a yellow one). For this, you just need to call setBackground() in the click listener.
For a fancier effect, you can use a TransitionDrawable to crossfade this change. startTransition() and reverseTransition() would then be used for the two state changes. For example:
Drawable d1 = getResources().getDrawable(R.drawable.follow_button);
Drawable d2 = getResources().getDrawable(R.drawable.unfollow_button);
final TransitionDrawable followDrawable = new TransitionDrawable(new Drawable[] { d1, d2 });
final int transitionDuration = getResources().getInteger(android.R.integer.config_shortAnimTime);
button.setBackground(followDrawable);
button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
if (!mFollowing)
{
mFollowing = true;
followDrawable.startTransition(transitionDuration);
}
else
{
mFollowing = false;
followDrawable.reverseTransition(transitionDuration);
}
}
});
First, you need to save your state. Whether it is "follow" or "unfollow". Where to save depends on your application logic.
Then, according to the current state, you can update the appearance of the button. What StateListDrawable does is, it update the background of your button based on the state whether it is "focused", "selected", etc.
You can use State List Drawable as a background of your button. Then, if the current state is "follow", you set your button as selected (vis Button.setSelected(true)). If the current state is "unfollow", it will be normal. (Button.setSelected(false).
<item android:drawable="#drawable/bg_for_follow" android:state_selected="true" />
<item android:drawable="#drawable/bg_for_unfollow" />
Something like this. In above example, if you set that drawable file as the background of your button, it would use "bg_for_follow" when the button state is "selected" and it would use "bg_for_unfollow" when the butotn state is normal.
Hope that could help.
Related
everyone. After clicking on an ImageView, I would like to change it depending on what kind of drawable is currently displayed. To do this, I compare the currently set image in the ImageView with one from the drawable folder. Unfortunately, it is currently the case that only the else branch is executed. The image changes after the first click, but then it no longer switches. What am I doing wrong?
bookmark_site.setOnClickListener{
vibrator.vibrate(50);
var draw = bookmark_site.drawable.constantState
if(draw == ContextCompat.getDrawable(this,R.drawable.ic_baseline_bookmark_filled_24)?.constantState)
{
bookmark_site.setImageDrawable(resources.getDrawable(R.drawable.ic_outline_bookmark_border_outline_24))
}
else{
//Only this two is ever executed
bookmark_site.setImageDrawable(resources.getDrawable(R.drawable.ic_baseline_bookmark_filled_24))
}
}
you can't base on constantState, its not desired to compare drawables as there is a different instance for every drawable, thus your if isn't true never ever. in fact there is no way for getting resource of drawable already set for ImageView. most convenient way would be to keep some boolean flag outside onClick method informing that image is switched or not. optionally you may keep this flag "inside" ImageView using setTag(...) method
bookmark_site.setOnClickListener{
vibrator.vibrate(50);
val switched = bookmark_site.tag != null
bookmark_site.setImageResource(
if (switched) R.drawable.ic_outline_bookmark_border_outline_24
else R.drawable.ic_baseline_bookmark_filled_24
)
bookmark_site.tag = if (switched) null else "SWITCHED"
}
you should keep category or tag along with the image in the model class and then change the image on the basis of that tag or category.
I am new to Android development. I am currently building an application that must flash different colors when a button is clicked. When the button is clicked I call a function. This function loops through a list of items and basically at the moment attempts to show blue and green after each other a couple of times. Problem is that it only shows the last color. And this only happens when the thread has exited the method. In the example below it is blue. I have noticed with some of the work I have done that screen changes reflects once the program have left the current method where the loop occurs and sometimes even longer after that. Below is the code :
//Method that sets the color
public void SetVisualLayoutColor(int Color)
{
linearLayout.setBackgroundColor(Color);
linearLayout.invalidate();
linearLayout.refreshDrawableState();
}
//Method that loops and calls above method to set color
public boolean ShowRepititive()
{
boolean successfull = false;
try
{
boolean isGreen = true;
//for (TimingItem timingItem : items) {
for (int i=0;i<=10;i++) {
if (isGreen) {
SetVisualLayoutColor(Color.BLUE);
isGreen = false;
} else
{
SetVisualLayoutColor(Color.BLUE);
isGreen = true;
}
}
successfull = true;
} catch (Exception e)
{
Log.e("Repeating Flash", "showFlashRepititive: ", e);
successfull = false;
}
return successfull;
}
Is there some way to get past this or to force the changes to occur timeously ?
Thank you in advance.
Unless you explicitly run your code on a different thread, the code you write in an Activity, Fragment, or View will run on the UI thread.
When you are performing work on the UI thread, the UI cannot update. The UI only updates after your code has finished executing. Thus your for loop blocks any UI updates until it completes, showing the last color you set.
A more appropriate pattern to use would be to use an animation to change the color
Here is an example of a very basic animation that does a cross-fade between two background colors:
ObjectAnimator.ofObject(view, "backgroundColor", new ArgbEvaluator(), 0xFF0000, 0x00FF00)
.start();
Obviously this won't achieve the flashing effect you are looking for, but you can define your own animations in a similar manner to achieve the desired effect.
As Tanis.7x said, you can't create the desired animation while your code is executed in the main thread. All potential solutions have to have a background Thread and a way for it to communicate with your UI thread. (see AsyncTasks,Threads,Handlers)
An alternative to ObjectAnimator that can work in your specific case is TransitionDrawable. It's not that powerful but if it suits your needs, it's preferable since it's API 1 compatible:
You need to store a transitioncolors.xml in your drawables folder with your transition definition:
<?xml version="1.0" encoding="UTF-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/green"/>
<item android:drawable="#color/blue"/>
</transition>
and then call:
ImageView view = (ImageView) findViewById(R.id.transitionId);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TransitionDrawable transition = (TransitionDrawable) v.getBackground();
transition.startTransition(3000);
});
where R.id.transitionId is:
<ImageView
android:id="#+id/transitionId"
android:background="#drawable/transitioncolors"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
I did some more research after I read Tanis.7x and Sevle's post, which put me in the right direction. For some reason the Object animator did not worked when I ran it and the Transition does not give me the flexibility I wanted. So I came across the ValueAnimator, which worked perfectly for me. I created my own class that extended the ValueAnimator and within the class I control how long each animation must be and also other aspects like running indefinitely until the user interrupts it on the screen. Thanks a lot guys, I really appreciate the help.
I need to see if there is a way where I can test for what background a button has. For example, here is my pseudo code:
if (button background is `R.drawable.black`) {
button.setBackground(to R.drawable.white)
}
Is there a way that this if statement can be done? I know how to SET backgrounds, just curious on the test portion.
In your case, I believe that tags would be useful. Try this:
//When you set the button:
btn.setBackgroundResource(R.drawable.black);
btn.setTag(R.drawable.black);
//When you re-set the button:
if(btn.getTag().equals(R.drawable.black)) {
btn.setBackgroundResource(R.drawable.white);
btn.setTag(R.drawable.white);
}
There is a getBackgroud method
Drawable buttonBackground = button.getBackground();
I'd like to gray out a button so it appears disabled to the user, but still listen for clicks so that I can display a message to the user that explains why the button isn't applicable.
I'd like to ensure that the Android API is the one configuring whatever is the appropriate standard disabled appearance as opposed to manually setting the button color to gray, etc. What's the best way to do this?
Related: Android - Listen to a disabled button
this is custom button which expose the event of touch when disabled
it working for sure, and tested. designed specific to you
public class MyObservableButton extends Button
{
public MyObservableButton(Context context, AttributeSet attrs)
{
super(context, attrs);
}
private IOnClickWhenEnabledListner mListner;
public void setOnClickWhenEnabledListener(IOnClickWhenEnabledListner listener) {
mListner = listener;
}
private interface IOnClickWhenEnabledListner {
public void onClickWhenEnabled();
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (!isEnabled() && mListner != null) {
mListner.onClickWhenEnabled();
}
}
return super.onTouchEvent(event);
}
}
this is the right way to accomplish what you want from my point of view as android developer.
there is no problem extanding all android's views, and use them on the xml files, and source instead..
good luck
You could also manually set the background of your Button to the default one for disabled. But leave the button enabled and handle the click events in the normal fashion
something like this should do it:
mBtn.setBackgroundResource(android.R.drawable.btn_default_normal_disabled);
I am not an Android expert, so there could be better ways, but what about disabling the button and overlaying a transparent view that will catch the events?
You could have the view always there laying below the button so you just need to change a z-index, or create it dynamically when needed.
If your button is on the newer types that controls color via backgroundTint rather then background, this is what you should do:
if (enabled) {
ViewCompat.setBackgroundTintList(btn, getResources().getColorStateList(R.color.button_states)); // either use a single color, or a state_list color resource
} else {
ViewCompat.setBackgroundTintList(btn, ColorStateList.valueOf(Color.GRAY));
}
// make sure we're always clickable
btn.setEnabled(true);
btn.setClickable(true);
You could also set the Button's style to look grayed out (for both pressed and non-pressed states), then setOnClickListener() as normal, but have the onClick() method give the message that it isn't clickable.
Since button extends textview. You may use the methods in textview such as .setTextColor() or .setBackgroundColor() .
Now for the the display you have 2 options:
AlertDialog - displays an alert but doesn't self close unless specified.
Toast - displays a text over a given time and self closes.
take your pick.
I want to create a Button that behaves like a switch.
It should change its color when the user clicks it, and keep the color.
So the button is white at first and when the user clicks it, the color changes to black. When the user clicks it again it switches back to white and so on.
I tried it with a simple if else construct but only managed to get the button to be white at first and when being clicked change to black, but it won´t change back to white when clicked again.
Here´s the code so far. I guess it´s a dumb simply mistake but can´t seem to get through with it. "changecolor" is a variable I declared myself.
// Select Button Safe or At-Risk
final Button button7 = (Button) findViewById(R.id.SafeBT);
button7.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
// Perform action on clicks, change color
if (changecolor == 0) {
button7.setBackgroundColor(color.black);
changecolor = 1;
} else {
button7.setBackgroundColor(color.white);
changecolor = 0;
}
}
});
Tanks for advice and help in advance.
where you have declared your variable changecolor?? .
Second thingis that you can simply an UI Element which call it : ToggleButton , it is like a Switch Button ON/OFF . is that what you want ? see this link : http://developer.android.com/reference/android/widget/ToggleButton.html