Change color of a particular RelativeLayout Android - java

I have a RelativeLayout:
<RelativeLayout
android:id="#+id/my_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/my_shape" >
The my_shape.xml is this:
<stroke
android:width="1dp"
android:color="#FFF"/>
<solid android:color="#000"/>
So, from my activity, i would change the color of this RelativeLayout.
I've tried with
RelativeLayout tvCard = (RelativeLayout) findViewById(R.id.my_id);
tvCard.setBackgroundColor(color);
N.B. color is an input color!
By this solution, the RelativeLayout is completely draw of red! How can i do to change color of it without change the "stroke color"?
Thank you.

try to create ShapeDrawable in java code.
like this:
ShapeDrawable sd1 = new ShapeDrawable(new RectShape());
sd1.getPaint().setColor(0xFFFFFFFF);
sd1.getPaint().setStyle(Style.STROKE);
sd1.getPaint().setStrokeWidth(1);
// sd1.getPaint().somehow_set_stroke_color?
ShapeDrawable sd2 = new ShapeDrawable(new RectShape());
sd2.getPaint().setColor(0xFF000000);
sd2.getPaint().setStyle(Style.STROKE);
// sd2.getPaint().somehow_set_stroke_color?
// sd2.getPaint().somehow_set_gradient_params?
layers[0] = sd1;
layers[1] = sd2;
LayerDrawable composite = new LayerDrawable(layers);
tvCard.setBackgroundDrawable(composite);

Related

Android/Java: How to change programmatically the color of a Drawable in a BottomNavigationView (with no color selection at initialization)?

I have a color by default in my XML, and I would like to change it programmatically. I don't know how to access to the highlight_color item color in the highlight_color.xml programmatically...
main java code:
//BEGIN TEST COLOR
ColorStateList iconsColorStates = new ColorStateList(
new int[][]{
new int[]{-android.R.attr.state_checked},
new int[]{android.R.attr.state_checked}
},
new int[]{
Color.parseColor("#000000"),
Color.parseColor("#ffffff")
});
ColorStateList textColorStates = new ColorStateList(
new int[][]{
new int[]{-android.R.attr.state_checked},
new int[]{android.R.attr.state_checked}
},
new int[]{
Color.parseColor("#000000"),
Color.parseColor("#ffffff")
});
//color ec5d60
bottomNavigation.setItemIconTintList(iconsColorStates);
bottomNavigation.setItemTextColor(textColorStates);
main XML:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/relativeLayout3"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LocalNav">
<WebView
android:id="#+id/vieweb"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="0dp"
android:layout_marginBottom="-2dp"
app:layout_constraintBottom_toTopOf="#+id/bottom_nav"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.NewTelApps.ToEvent.newBottomNav
android:id="#+id/bottom_nav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
app:itemIconSize="45dp"
android:visible="false"
app:itemBackground="#drawable/nav_item_drawable"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/bottom_nav_menu"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
nav_item_drawable.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/highlight_color" android:state_checked="true"/>
</selector>
highlight_color.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#ec5d60"/>
</shape>
EDIT:
This two piece of codes (took from the different answers) change well the color, but the display is not good:
1/
Drawable drawable = AppCompatResources.getDrawable(context,
R.drawable.nav_item_drawable);
drawable.setColorFilter(getResources().getColor(android.R.color.holo_green_light), PorterDuff.Mode.MULTIPLY);
bottomNavigation.setItemBackground(drawable);
2/
Drawable unwrappedDrawable = AppCompatResources.getDrawable(context,
R.drawable.nav_item_drawable);
Drawable wrappedDrawable = DrawableCompat.wrap(unwrappedDrawable);
DrawableCompat.setTint(wrappedDrawable, Color.GREEN);
Before adding this piece of code:
After adding this piece of code:
EDIT2:
I finally find the way to correct the problem. I simply had to put the piece of code in a loop just before the color item tint and text. Here is my full code:
Main Java class
int itemSelected = this.getSelectedItem(this);
Log.d("Item Selected :", String.valueOf(itemSelected));
Log.d("Number of items :", String.valueOf(this.getMenu().size()));
if (initialization == 0)
{
this.getMenu().setGroupCheckable(0, true, false);
for (int j = 0; j < this.getMenu().size(); j++) {
this.getMenu().getItem(j).setChecked(false);
}
this.getMenu().setGroupCheckable(0, true, true);
}
final ViewGroup bottomMenu = (ViewGroup)getChildAt(0);
final int bottomMenuChildCount = bottomMenu.getChildCount();
BottomNavigationItemView item = null;
View itemTitle;
for(int i=0; i<bottomMenuChildCount; i++){
item = (BottomNavigationItemView)bottomMenu.getChildAt(i);
//this shows all titles of items
item.setChecked(true);
//every BottomNavigationItemView has two children, first is an itemIcon and second is an itemTitle
itemTitle = item.getChildAt(1);
//every itemTitle has two children, first is a smallLabel and second is a largeLabel. these two are type of AppCompatTextView
((TextView)((BaselineLayout) itemTitle).getChildAt(0)).setTextSize(10);
((TextView)((BaselineLayout) itemTitle).getChildAt(0)).setGravity(Gravity.CENTER_HORIZONTAL);
((TextView)((BaselineLayout) itemTitle).getChildAt(1)).setTextSize(10);
((TextView)((BaselineLayout) itemTitle).getChildAt(1)).setGravity(Gravity.CENTER_HORIZONTAL);
Drawable drawable = AppCompatResources.getDrawable(context,
R.drawable.nav_item_drawable);
drawable.setColorFilter(getResources().getColor(android.R.color.holo_green_light), PorterDuff.Mode.SRC_ATOP);
item.setItemBackground(drawable);
}
//BEGIN TEST COLOR
ColorStateList iconsColorStates = new ColorStateList(
new int[][]{
new int[]{-android.R.attr.state_checked},
new int[]{android.R.attr.state_checked}
},
new int[]{
Color.parseColor("#000000"),
Color.parseColor("#ffffff")
});
ColorStateList textColorStates = new ColorStateList(
new int[][]{
new int[]{-android.R.attr.state_checked},
new int[]{android.R.attr.state_checked}
},
new int[]{
Color.parseColor("#000000"),
Color.parseColor("#ffffff")
});
//color ec5d60
bottomNavigation.setItemIconTintList(iconsColorStates);
bottomNavigation.setItemTextColor(textColorStates);
Thanks in advance.
You can try this :)
Drawable unwrappedDrawable = AppCompatResources.getDrawable(context,
R.drawable.my_drawable);
Drawable wrappedDrawable = DrawableCompat.wrap(unwrappedDrawable);
DrawableCompat.setTint(wrappedDrawable, Color.RED);
You can change the background color programmatically as:
Drawable drawable = AppCompatResources.getDrawable(context,
R.drawable.nav_item_drawable);
drawable.setColorFilter(getResources().getColor(android.R.color.holo_red_dark), PorterDuff.Mode.MULTIPLY);
bottomNavigationView.setItemBackground(drawable);
And keep the app:itemBackground="#drawable/nav_item_drawable" of your BottomNavigationView
Hope it targets it!

How to change stroke color of a drawable with Kotlin or Java

I have a drawable object that I use to set the background of a linear layout, leaving the linear with the circular shape with a semi transparent orange line. but at some point in the code I need to change the color of this background (drawable object) to a color that I have only as a parameter and I don't have it in the colors of my color file. I need to change the stroke color of this drawable to a color that I have in one of my runtime variables
bg_static_show_password.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<!-- center circle -->
<stroke android:color="#color/accent_color_alpha"
android:width="3dp" />
<solid android:color="#android:color/transparent" />
<size
android:width="28dp"
android:height="28dp"/>
</shape>
linear layout
<android.support.constraint.ConstraintLayout
android:id="#+id/card_show_password"
android:layout_width="#dimen/anim_layout_size"
android:layout_height="#dimen/anim_layout_size"
android:layout_marginTop="#dimen/anim_margin_top"
android:background="#drawable/bg_static_show_password"
android:layout_gravity="center"
app:layout_constraintTop_toBottomOf="#id/view_group_item"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
method I'm trying to use to make this color change
fun showAlternativeForAnimation(view: LinearLayout) {
val drawable = view.background as GradientDrawable
val theme = PasswordRecoveryTheme(ApplicationSession.instance?.themeId)
drawable.setStroke(1, theme.getAccentColor(ApplicationFactory.context!!))
}
the parameter of method is the LinearLayout
When I try, I get this exception:
kotlin.TypeCastException: null cannot be cast to non-null type android.graphics.drawable.GradientDrawable
Make a safe cast (as?), ensure that the view you pass has a shape drawable set as it's background and change parameter to view: View so as to allow usage for any view(LinearLayout, ConstraintLayout, etc).
fun showAlternativeForAnimation(view: View) {
val drawable = view.background as? GradientDrawable
val theme = PasswordRecoveryTheme(ApplicationSession.instance?.themeId)
drawable?.setStroke(1, theme.getAccentColor(ApplicationFactory.context!!))
}

Change BackgroundTint of ImageView on Android

I have an ImageButton which have a drawable background resource which is oval shape.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:angle="270"
android:color="#FFFF0000" />
</shape>
Here is the ImageButton in XML:
<ImageButton
android:id="#+id/c1"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_columnSpan="1"
android:layout_rowSpan="1"
android:background="#drawable/circle"
android:layout_margin="10dp"
/>
I need to change the color of the circle shape dynamically, this will be done by either change the backgroundTint property in the ImageButton or change the circle shape color.
NOTE:
I have array of strings that stores a list of RGB colors i need to use these RGB colors.
You can do it like this:
mImageView.setBackgroundTintList(getResources().getColorStateList(R.color.my_color));
Or you can do better, to support versions pre LOLLIPOP:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
ColorStateList stateList = ColorStateList.valueOf(getResources().getColor(R.color.my_color));
mImageView.setBackgroundTintList(stateList);
}
else
{
mImageView.getBackground().getCurrent().setColorFilter(
new PorterDuffColorFilter(getResources().getColor(R.color.my_color),
PorterDuff.Mode.MULTIPLY));
}
More about PorterDuffColorFilter here.
i just found the answer, it works as follow:
In my changeColors(int id) function
Create ImageButton variable.
Assign the passed id to the ImageButton variable.
Define GradientDrawable variable to store the ImageButton background.
Update the color of the background using GradientDrawable variable.
Update the ImageButton to the new background.
This is the code:
ImageButton circle;
circle = (ImageButton) findViewById(id);
GradientDrawable drawable = (GradientDrawable) getResources().getDrawable(R.drawable.circle);
drawable.setColor(Color.parseColor("color in format #FFFFFF");
circle.setBackground(drawable);
You may use ImageView instead and use app:tint to set the tint color for the background drawable.
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:src="#drawable/circle"
app:tint="#android:color/holo_red_dark"/>

How to change the stroke width of a shape programmatically in Android?

This is circle.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#00000000"/>
<padding android:left="30dp" android:top="30dp"
android:right="30dp" android:bottom="30dp" />
<stroke android:color="#439CC8" android:width="7dp" />
</shape>
This is my code:
textview.setBackgroundResource(R.drawable.circle);
I want to change the stroke thickness in my java code. How can I change it programmatically?
Do like this:
1) Get the TextView using the usual findViewById() :
TextView textView = (TextView) rootView.findViewById(R.id.resourceName);
2) Get the Drawable from TextView using getBackground() and cast it to GradientDrawable:
GradientDrawable backgroundGradient = (GradientDrawable) textView.getBackground();
3) Apply it a stroke using setStroke() method (pass it the width in pixel and the color):
backgroundGradient.setStroke(5, Color.BLACK);
Whole code:
TextView textView = (TextView) rootView.findViewById(R.id.resourceName);
GradientDrawable backgroundGradient = (GradientDrawable) textView.getBackground();
backgroundGradient.setStroke(5, Color.BLACK);
You may need to create it programmatically
ShapeDrawable circle = new ShapeDrawable( new OvalShape() );
you need to set the properties after this, ( padding, color, etc) then change its stroke
circle.getPaint().setStrokeWidth(12);
then set it as the background for the view
textview.setBackgroundDrawable(circle);

Programmatically rotate drawable or view [duplicate]

Could anyone tell me how they have got RotateDrawable to work whether it be from code or XML or both? The documentation on animating Drawables is pretty poor and animation only seems to work for images. I want to be able to animate all drawables. When i tried to get a RotateDrawble from XML is just causes an exception. What is the correct function to find a RotateDrawable from XML?
here's a nice solution for putting a rotated drawable for an imageView:
Drawable getRotateDrawable(final Bitmap b, final float angle) {
final BitmapDrawable drawable = new BitmapDrawable(getResources(), b) {
#Override
public void draw(final Canvas canvas) {
canvas.save();
canvas.rotate(angle, b.getWidth() / 2, b.getHeight() / 2);
super.draw(canvas);
canvas.restore();
}
};
return drawable;
}
usage:
Bitmap b=...
float angle=...
final Drawable rotatedDrawable = getRotateDrawable(b,angle);
root.setImageDrawable(rotatedDrawable);
another alternative:
private Drawable getRotateDrawable(final Drawable d, final float angle) {
final Drawable[] arD = { d };
return new LayerDrawable(arD) {
#Override
public void draw(final Canvas canvas) {
canvas.save();
canvas.rotate(angle, d.getBounds().width() / 2, d.getBounds().height() / 2);
super.draw(canvas);
canvas.restore();
}
};
}
also, if you wish to rotate the bitmap, but afraid of OOM, you can use an NDK solution i've made here
You have to animate the "level" property, where 0 is the start value and 10000 is the end value.
The below example animates from start to finish, you can reverse the animation easily with this method.
final RotateDrawable rotateDrawable = ...
ObjectAnimator.ofInt(rotateDrawable, "level", 0, 10000).start();
I would like to add a full example of animating a progress icon on ImageView, it is based on Mark Hetherington answer.
So my animation looks as follows:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="0"
android:toDegrees="-360"
android:duration="100"
android:drawable="#drawable/ic_loop_black_24dp"
/>
icon comes from https://material.io/icons/
then my layout contains an ImageView as follows:
<ImageView
android:id="#+id/progress"
android:layout_marginTop="0dp"
android:layout_marginLeft="-3dp"
android:layout_width="30dp"
android:layout_height="30dp"
android:visibility="gone"
android:scaleType="fitCenter"
android:background="#drawable/progress_anim"
android:layout_gravity="center_horizontal|center_vertical"
/>
and finally in code when I need to show animation I do:
RotateDrawable rotateDrawable = ((RotateDrawable)progressImage.getBackground());
ObjectAnimator anim = ObjectAnimator.ofInt(rotateDrawable, "level", 0, 10000);
anim.setDuration(1000);
anim.setRepeatCount(ValueAnimator.INFINITE);
anim.start();
RotateDrawable does not seem to be animated. Instead, you have to use setLevel to change the rotation of the drawable.
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="#drawable/your_drawable"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
And set the level will rotate the drawable:
final ImageView image = (ImageView)findViewById(R.id.imageView1);
final RotateDrawable drawable = (RotateDrawable)image.getDrawable();
drawable.setLevel(500);
The following code returns a Drawable wrapper that rotates another Drawable programmatically:
Drawable rotateDrawable(Drawable d, final float angle) {
// Use LayerDrawable, because it's simpler than RotateDrawable.
Drawable[] arD = {
d
};
return new LayerDrawable(arD) {
#Override
public void draw(Canvas canvas) {
canvas.save();
canvas.rotate(angle);
super.draw(canvas);
canvas.restore();
}
};
}
I haven't worked with a RotateDrawable, but if you're simply trying to animate rotation on a graphic, you don't need it. Drawables with a 'level' like RotateDrawable are meant to convey information rather than animate views.
The following code rotates an ImageView around its center:
ImageView myImageView = (ImageView)findViewById(R.id.my_imageview);
AnimationSet animSet = new AnimationSet(true);
animSet.setInterpolator(new DecelerateInterpolator());
animSet.setFillAfter(true);
animSet.setFillEnabled(true);
final RotateAnimation animRotate = new RotateAnimation(0.0f, -90.0f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
animRotate.setDuration(1500);
animRotate.setFillAfter(true);
animSet.addAnimation(animRotate);
myImageView.startAnimation(animSet);
Since you're trying to use Almero's Android Gesture Detectors, I decided to do the same in order to find an appropriate solution:
public class MainActivity extends Activity {
private RotateGestureDetector mRotateDetector;
private float mRotationDegrees = 0.f;
private static final float ROTATION_RATIO = 2;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRotateDetector = new RotateGestureDetector(getApplicationContext(), new RotateListener());
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mRotateDetector.onTouchEvent(event);
return super.onTouchEvent(event);
}
private class RotateListener extends RotateGestureDetector.SimpleOnRotateGestureListener {
#Override
public boolean onRotate(RotateGestureDetector detector) {
mRotationDegrees -= detector.getRotationDegreesDelta();
ImageView v = (ImageView) findViewById(R.id.imageView);
// For NineOldAndroids library only!
ViewHelper.setRotation(v, mRotationDegrees * ROTATION_RATIO);
// For HONEYCOMB and later only!
v.setRotation(mRotationDegrees * ROTATION_RATIO);
return true;
}
}
}
It works fine for me (I'm able to rotate the ImageView with two-finger rotation gesture.
NOTE: Don't forget to chose appropriate rotation method call. I commented both of them to draw your attention.
ROTATION_RATIO is just a multiplier to speed-up a rotation response on my fingers movement.
You can use any rotation axis (setRotation(), setRotationX() and setRotationY()) methods for a View.
To enable support of this code on Android devices with API Level lower than 11 (pre-Honeycomb devices) you may want to engage NineOldAndroid library.
You could manually call RotatedDrawable.setLevel() to rotate the drawable, or you could read the code of ProgressBar, the indeterminate drawable is a LayerDrawable whose children were RotatedDrawable, like this one:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate
android:drawable="#drawable/spinner_48_outer_holo"
android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="0"
android:toDegrees="1080" />
</item>
<item>
<rotate
android:drawable="#drawable/spinner_48_inner_holo"
android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="720"
android:toDegrees="0" />
</item>
</layer-list>
The rotate animation was driven by ProgressBar's onDraw method.
This is a good working example. Param duration is used to animate it.
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="720" >
<shape
android:innerRadius="20dp"
android:shape="ring"
android:thickness="4dp"
android:useLevel="false" >
<size
android:height="48dp"
android:width="48dp" />
<gradient
android:centerY="0.5"
android:endColor="#android:color/white"
android:startColor="#00ffffff"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
If you want to rotate drawable forever you can use animated-rotate tag in drawable xml like this.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<animated-rotate android:drawable="#drawable/ic_refresh" android:pivotX="50%" android:pivotY="50%" />
</item>
</selector>

Categories

Resources