Android Changing Seekbar Thumb with Java causes Thumb position to Reset - java

I am trying to create a seekbar with a thumb that changes color when it is pressed by the user and change back when the user lets go. I managed to change the thumb drawable using set thumb. However, I also had to set the drawable boundries in java to get it to appear after the change. Now when the user lets go of the slider and it reverts to its original drawable it resets the drawable to the zero position and leaves the progress where it should be. I have tried using a global variable to reset the seekbar progress after the drawable is changed, but it doesn't seems to work. If I use a static integer to reset the progress it works the way I want it to.
Kinda new to android and I don't know what I am doing wrong.
This is the code that changes the drawable when it is touched.
private void Seek_Height_Click() {
Drawable myThumb = getResources().getDrawable(R.drawable.slider_button_click);
myThumb.setBounds(new Rect(0, 0, myThumb.getIntrinsicWidth(),myThumb.getIntrinsicHeight()));
Height_of_Target_skbr.setThumb(myThumb);
Height_of_Target_skbr.setThumbOffset(-1);
}
This is the code to set the thumb back to the original drawable.
private void Seek_Height_UnClick() {
Drawable myThumb = getResources().getDrawable(R.drawable.slider_button);
myThumb.setBounds(new Rect(0, 0, myThumb.getIntrinsicWidth(),myThumb.getIntrinsicHeight()));
Height_of_Target_skbr.setThumb(myThumb);
Height_of_Target_skbr.setThumbOffset(-1);
Height_of_Target_skbr.setProgress(Height_Prog_int);
}
This is the code that calls the above method.
this.Height_of_Target_skbr.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
returnHeight_skbr();
Seek_Height_UnClick();
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
returnHeight_skbr();
Seek_Height_Click();
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
returnHeight_skbr();
}
});

I was able to make this work using by creating a style in the drawable folder and then setting the thumb drawable to that style.
I refereed to this tutorial to make this work.
http://www.youtube.com/watch?v=zXXCFmfJMNw
Code for Thumb Style
<?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/slider_button_click">
</item>
<item
android:drawable="#drawable/slider_button">
</item>
</selector>

Related

change tint of button programmatically

I simply want to change the backgroundTint of a normal button from inside the java code. I tried many different approaches like ColorStateList or setColorFilter, but nothing worked. I am purposefully not using setBackgroundColor since I want to keep the original shape of the button.
Furthermore, the colors I want to use are already defined in my resources. After lots of trial and error I managed to access these colors with this code:
int colorBtnDeactivated = ContextCompat.getColor(this, R.color.colorBtnDeactivated);
So basically I only need this one line of java code which enables me to access the background tint. The rest I can do myself.
I would really appreciate help, I have been stuck on this problem for hours. Thanks!
Edit: Using a selector-xlm didn't work, since it only changed the color of the button while being pressed. Also the buttons will influence each other, so by pressing one button I will need to be able to change the background tint of another button.
Edit 2: I tried again with setColorFilter:
//this is all inside the onCreate-method
int colorBtnActiveTest= ContextCompat.getColor(this, colorBtnActive);
int colorBtnDeactivatedTest=ContextCompat.getColor(this, colorBtnDeactivated);
Button btnKnockOne = (Button)findViewById(R.id.btnKnockOne);
boolean stateBtnKnockOne = false;
btnKnockOne.getBackground().setColorFilter(colorBtnDeactivatedTest, PorterDuff.Mode.SRC_IN);
btnKnockOne.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (stateBtnKnockOne==false){
btnKnockOne.getBackground().setColorFilter(colorBtnActiveTest, PorterDuff.Mode.SRC_IN);
stateBtnKnockOne=true;
}
else if (stateBtnKnockOne==true){
btnKnockOne.getBackground().setColorFilter(colorBtnDeactivatedTest, PorterDuff.Mode.SRC_IN);
stateBtnKnockOne=false;
}
}
});
This is the result:
When I open the activity, the button is displayed in the default grey button color, not in my custom color colorBtnDeactivatedTest
When I press the button, it briefly changes its color to colorBtnActiveTest, but then goes back to its grey color
I finally found a solution! This post helped me find it: https://stackoverflow.com/a/8748112/8952749
Now I basically have two buttons of which only one can be selected at one time. For this to work I created a selector-xlm:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="true"
android:drawable="#drawable/button_active" />
<item
android:state_selected="false"
android:drawable="#drawable/button_deactivated" />
</selector>
This is the java code, which enables me to change state_selected of the buttons:
stateBtn1=false;
stateBtn2=false;
btnTest1=(Button)findViewById(R.id.button);
btnTest2=(Button)findViewById(R.id.button2);
btnTest1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (stateBtn1==false){
btnTest1.setSelected(true);
stateBtn1=true;
btnTest2.setSelected(false);
stateBtn2=false;
}
else if (stateBtn1==true){
btnTest1.setSelected(false);
stateBtn1=false;
}
}
});
btnTest2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (stateBtn2==false){
btnTest2.setSelected(true);
stateBtn2=true;
btnTest1.setSelected(false);
stateBtn1=false;
}
else if (stateBtn2==true){
btnTest2.setSelected(false);
stateBtn2=false;
}
}
});

Android: checking a view's background

I have 3 buttons, all of them have the same background drawable by default (subject_button)
What I want to do:
When I click one button his background changes ( to clicked_subject), all the others remain with the default background, if I click one button after clicking another, the button I just clicked changes his background while the previous one gets back to the initial background, allowing only one button to have the clicked_subject background, if the diffrent button gets clicked again his background goes back to the initial one, leting all the buttons with the initial background.
The problem:
If I click the diffrent button, his background remains the same instead of changing back to the initial one.
My logic:
theButton1.setBackgroundResource(R.drawable.subject_button);
theButton1.setOnClickListener(this);
//same for other 2
#Override
public void onClick(View v) {
if (v.getBackground() == ContextCompat.getDrawable(this, R.drawable.subject_button)) {
theButton1.setBackgroundResource(R.drawable.subject_button);
theButton2.setBackgroundResource(R.drawable.subject_button);
theButton3.setBackgroundResource(R.drawable.subject_button);
v.setBackgroundResource(R.drawable.clicked_subject);
} else {
v.setBackgroundResource(R.drawable.subject_button);
}
Why is this happening?
You can do this:
private final List<Button> mButtons = new ArrayList<>();
// somewhere in your code
mButtons.add(mButton1);
mButtons.add(mButton2);
mButtons.add(mButton3);
mButton1.setOnClickListener(mClickListener);
mButton2.setOnClickListener(mClickListener);
mButton3.setOnClickListener(mClickListener);
private final View.OnClickListener mClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
for (Button button : mButtons) {
if (button == v) {
// set selected background
} else {
// set not selected backround
}
}
}
};
If you define a stateful drawable for your buttons, then you can simply change the onclick to this:
private final View.OnClickListener mClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
for (Button button : mButtons) {
button.setSelected(v == button);
}
}
};
For changing background color/image based on the particular event(focus, press, normal), you need to define a button selector file and implement it as background for button. For example button_selector.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/your_image1" /> <!-- pressed -->
<item android:state_focused="true"
android:drawable="#drawable/your_image2" /> <!-- focused -->
android:drawable="#drawable/your_image3" <!-- default -->
</selector>
then just apply it as :
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawable="#drawable/button_selector.xml" />
I solved it by instead of changing only the background color on clicking the button, I also change the textColor, then I can check the textColor with if (((Button) v).getCurrentTextColor() == Color.WHITE)
"Pressed", "selected", "disabled" and such are View states. As such they're supposed to be handled automatically by Android and not by your click listeners.
This is achieved using SateLists, which control the look your Views sould have depending on which state(s) they're in. So you can easily set subject_button as the unpressed state, clicked_subject as the pressed state, and let Android take care of actually switching between them.
Full explanation: https://developer.android.com/guide/topics/resources/drawable-resource.html#StateList

How to change colors in an android app?

I want to change colors in my options menu for color blind people, I was thinking of having two strings.xml files and switch between them on button press. What is the proper way of changing colors of ImageButton that has colors declared in strings.xml ?
final Switch colorsChange= (Switch) findViewById(R.id.switch_colors);
colorsChange.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
// Color blind friendly colors here
} else {
// Normal RGB colors here
getResources().getColor(R.color.defaultColors);
}
}
});
I want to carry these settings across all activities if possible
button.setColor(Color.RED);
or you can using button.setColor(code color);
You should define color in color.xml (in "values" directory)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="color_name">#e6e6e6</color>
</resources>
and reference to it:
In xml file:
#color/color_name
In Java class:
getResources().getColor(R.color.color_name);
Add colors you want into your resources
Give action to your button using android:onClick="methodName"
In your java method get the color by using getResources().getColor(R.color.idname);
You should declare colors in colors.xml
But still,
In string.xml you should declare <string name="red">#ff0000</string>
ImageButton.setBackgroundColor(Color.parseColor(getString(R.string.red));//if using string.xml
or
ImageButton.setBackgroundColor(ContextCompat.getColor(mContext, R.color.red));//if using colors.xml
Or, alternatively:
ImageButton.setBackgroundColor(Color.RED); // From android.graphics.Color
Or, for more pro skills:
ImageButton.setBackgroundColor(0xFFFF0000); // 0xAARRGGBB
Documentation

Android ObjectAnimator fill after option?

In my android application I am using an ObjectAnimator to translate an imageview like so:
ObjectAnimator transitionX = ObjectAnimator.ofFloat(v, "TranslationY", 190);
Is there an option like fillAfter that will reset the position of the view to the new position, after the animation is complete?
Nope, I'd use the property animation system instead, assuming v is a view:
v.animate().translationY(190).withEndAction(new Runnable() {
#Override
public void run() {
v.setTranslationY(v.getTranslationY()-190);
}
}).start();
Nope, there is no option for that. However you can achieve the same effect using a listener where you can manually change it to the initial position in the onAnimationEnd(). Here is an example for scaling an imageview:
scaleDown.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
//Initial property values
tempIV.setScaleX(1f);
tempIV.setScaleY(1f);
tempIV.setAlpha(1f);
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
I think the right way to handle this is to use an AnimationSet to merge two animations, one to translate and one to translate back the view.
Something like this
ObjectAnimator translateTo190= ObjectAnimator.ofFloat(v, "TranslationY", 190);
ObjectAnimator translateBack = ObjectAnimator.ofFloat(v, "TranslationY", 0);
AnimatorSet translate= new AnimatorSet();
translate.play(translateTo190).before(translateBack);
translate.start();
I have had a problem like this in writing a card dealing animation where the cards are dealt quickly from a central "deck". After much trial-and-error, the way I've got this working is using the ObjectAnimator in the following way.
I add a single "deck" card at the source of the animation, and then a second card that I'm actually animating. I use the following deal_from_drawpile.xml to animate the card in two parts: the first part returns the card to the source, and the second part scales and rotates the card as it is "dealt":
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/accelerate_interpolator"
android:ordering="sequentially">
<set android:interpolator="#android:anim/accelerate_interpolator"
android:ordering="together">
<objectAnimator
android:propertyName="translationX"
android:duration="10"
android:valueFrom="0.0f"
android:valueTo="0.0f"/>
<objectAnimator
android:propertyName="translationY"
android:duration="10"
android:valueFrom="0.0f"
android:valueTo="0.0f"/>
<objectAnimator
android:propertyName="scaleX"
android:duration="10"
android:valueFrom="0.75f"
android:valueTo="0.75f"/>
<objectAnimator
android:propertyName="scaleY"
android:duration="10"
android:valueFrom="0.75f"
android:valueTo="0.75f"/>
</set>
<set android:ordering="together">
<objectAnimator
android:propertyName="rotation"
android:duration="300"
android:valueFrom="0.0f"
android:valueTo="360.0f"/>
<objectAnimator
android:propertyName="scaleX"
android:duration="300"
android:valueFrom="0.75f"
android:valueTo="0.5f"/>
<objectAnimator
android:propertyName="scaleY"
android:duration="300"
android:valueFrom="0.75f"
android:valueTo="0.5f"/>
</set>
Then in code I add the actual translation which depends on how many hands are arranged in a rough semi-circle. The complete sequence of animations is then added in an AnimatorSet and fired off at the end. Code-snippet;
fullScreenContent.addView(dealtCardView);
for (int iCard=0; iCard<numCards; iCard++) {
for (int iPlayer = 0; iPlayer < numPlayers; iPlayer++) {
dealtCardAnimator = dealtCardAnimator.clone();
dealtCardAnimator.setTarget(dealtCardView);
//offsets where the cards are dealt according to player
ObjectAnimator playerOffsetXAnimator = ObjectAnimator.ofFloat(dealtCardView, "TranslationX", mGame.getPlayer(iPlayer).getPlayerLayout().getTranslationX());
ObjectAnimator playerOffsetYAnimator = ObjectAnimator.ofFloat(dealtCardView, "TranslationY", mGame.getPlayer(iPlayer).getPlayerLayout().getTranslationY());
if (lastDealtCardAnimator == null) dealSet.play(dealtCardAnimator).with(playerOffsetXAnimator).with(playerOffsetYAnimator);
else dealSet.play(dealtCardAnimator).with(playerOffsetXAnimator).with(playerOffsetYAnimator).after(lastDealtCardAnimator);
//The card is returned to the home point with the first portion of deal_from_drawpile
lastDealtCardAnimator = dealtCardAnimator;
}//end for iPlayer
}//end for numCards
dealSet.start();
I can now tinker with the duration of each step in the XML to get the effect I want. Note that you have to embed the duration in each element , not in the set section (where it is ignored, and some arbitrary default seems to be used instead).

Highlight text row in TextView including all width

I have already looked through some solutions of how to highlight some text in TextView using Spannable class. But it only allows to highlight a snippet which consists of characters. And what if I want to highlight a text row including TextView's width, but a text in this row doesn't fill whole view's width?
If anybody had an experience in such cases I would be glad to take an advice.
Update:
Ok, I hope following images will bring some clarity of my aim.
This is waht I can achieve using Spannable:
And this is what I want:
I really hope that it's clear.
There might be an easier way to do this, but I believe you will need to implement a class that implements LineBackgroundSpan to do what you want. Here's some sample code:
public class MyActivity extends Activity {
private static class MySpan implements LineBackgroundSpan {
private final int color;
public MySpan(int color) {
this.color = color;
}
#Override
public void drawBackground(Canvas c, Paint p, int left, int right, int top, int baseline,
int bottom, CharSequence text, int start, int end, int lnum) {
final int paintColor = p.getColor();
p.setColor(color);
c.drawRect(new Rect(left, top, right, bottom), p);
p.setColor(paintColor);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final TextView tv = new TextView(this);
setContentView(tv);
tv.setText("Lines:\n", BufferType.EDITABLE);
appendLine(tv.getEditableText(), "123456 123 12345678\n", Color.BLACK);
appendLine(tv.getEditableText(), "123456 123 12345678\n", Color.RED);
appendLine(tv.getEditableText(), "123456 123 12345678\n", Color.BLACK);
}
private void appendLine(Editable text, String string, int color) {
final int start = text.length();
text.append(string);
final int end = text.length();
text.setSpan(new MySpan(color), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
you can do android:padding="5dp" in your xml layout file and you can highlight noramlly through style xml and Spannable String Hope it will work welcome
TextView TV = (TextView)findViewById(R.id.text);
TV.setText("Italic, highlighted, bold.", TextView.BufferType.SPANNABLE);
Spannable WordtoSpan = (Spannable) TV.getText();
WordtoSpan.setSpan(new BackgroundColorSpan(0xFFFFFF00), 8, 19, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
TV.setText(WordtoSpan);
Link1
This may help you
Save below code in drawable folder
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="<<your color code"/>
</shape>
and specify textview background as below
android:background="#drawable/<<your file name>>"
What you are trying to do can be done more easily using StateListDrawable.
Make all your TextView's focusable in touch mode. Define statelistdrawables for the textview's background color and text color, and call requestFocus() whenever you want to highlight a textview.
StateListDrawable for textview's background :
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_focused="true"
android:drawable="#0F0" />
<item android:drawable="#0000" />
</selector>
Similarly define a selector list for text color.

Categories