Android Drawable color runtime - android

I am developing an android app. I have two different text view with different text view as shown in below two images:
Text view one:
Text view Two:
I have a question, should I create two different drawable files with different colors or should I create a single drawable file and change the color runtime?
What's the standard way to achieve this?
If I should create a single drawable file then how should I change to color programmatically?

try this simple example
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tvWelcome = findViewById(R.id.tv_welcome);
TextView tvHello = findViewById(R.id.tv_hello);
recolor(this, tvWelcome, getResources().getColor(R.color.red));
recolor(this, tvHello, getResources().getColor(R.color.green));
}
private void recolor(Context context, TextView textView, #ColorInt int color) {
Drawable unwrappedDrawable = AppCompatResources.getDrawable(context, R.drawable.item_background);
if (unwrappedDrawable != null) {
DrawableCompat.wrap(unwrappedDrawable);
DrawableCompat.setTint(unwrappedDrawable, color);
textView.setBackground(unwrappedDrawable);
}
}
}
item_background.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ffffffff" />
<corners
android:bottomLeftRadius="7dp"
android:bottomRightRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp" />
</shape>

Related

Android CardView - How to fold corner

I want to get a CardView with the top-right corner like you can see in the image below, but I have no idea how to do so. It is like a folded paper (with no animation). I don't know if I should make a custom background drawable or how to manage the corner radius to get the desired result. Any help will be greatly appreciated, thanks
Also you can create such a drawable programmatically like this:
public static final class FoldCornerCard extends Shape {
private final float foldPart;
private final Path cardPath = new Path();
private final Path foldPath = new Path();
private final Paint foldPaint;
public FoldCornerCard(int foldColor, float foldPart) {
if (foldPart <= 0 || foldPart >= 1) {
throw new IllegalArgumentException("Fold part must be in (0,1)");
}
this.foldPart = foldPart;
this.foldPaint = new Paint();
foldPaint.setAntiAlias(true);
foldPaint.setColor(foldColor);
}
#Override
protected void onResize(float width, float height) {
super.onResize(width, height);
this.cardPath.reset();
final float leftFold = width - width * foldPart;
final float bottomFold = height * foldPart;
cardPath.lineTo(leftFold, 0);
cardPath.lineTo(width, bottomFold);
cardPath.lineTo(width, height);
cardPath.lineTo(0, height);
cardPath.close();
foldPath.reset();
foldPath.moveTo(leftFold, 0);
foldPath.lineTo(leftFold, bottomFold);
foldPath.lineTo(width, bottomFold);
foldPath.close();
}
#Override
public void draw(Canvas canvas, Paint paint) {
canvas.drawPath(cardPath, paint);
canvas.drawPath(foldPath, foldPaint);
}
}
And usage example:
final ShapeDrawable shapeDrawable = new ShapeDrawable(
new FoldCornerCard(Color.GREEN, 0.1f));
shapeDrawable.getPaint().setColor(Color.WHITE);
shapeDrawable.setIntrinsicHeight(-1);
shapeDrawable.setIntrinsicWidth(-1);
You just need to modify my snippet a bit to add round corners.
Look at here https://developer.android.com/studio/write/draw9patch.html
I think this is righ way to use custom layout. You could draw it on xml, or use 9-patch png.
Also you can create own class MyCardView and extends from CardView, then override method onDraw and draw CardView like you want, but it is not good idea.
I would reccomend you use 9-patch image
You can achieve this using your xml:
Lets Assume our xml shape is called shape.xml
In shape.xml(Which you have to create in your drawable folder..drawable/shape.xml)..
Create your layer list element with its square shape as the background of your xml:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!--Paper-Back-->
<item
android:bottom="30dp"
android:left="18dp"
android:right="1dp"
android:top="0dp">
<shape android:shape="rectangle">
<solid android:color="#color/paperBack"/>
<corners
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="78dp"/>
</shape>
</item>
<!--Paper-Back End-->
<!--Fold-->
<item
android:bottom="650dp"
android:top="0dp"
android:left="300dp"
android:right="1dp">
<shape android:shape="rectangle">
<solid android:color="#color/paperFold"/>
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="0dp"
android:topRightRadius="100dp"
/>
</shape>
</item>
<!--Fold End-->
</layer-list>
Then in your colours.xml resource:
Add your colours:
color.xml
<color name="PaperBack">#A6F5F5F5</color>
<color name="paperFold">#A6DDDDDD</color>
In order to achieve the best results:The opacity of your colours as well as the type of colour combination for your paper background and fold colours will have to be taken into great consideration.
Now to apply the paper fold shape..in your main xml, use the shape.xml as the background in your main.xml.
using shape.xml as the background
android:background="#drawable/shape.xml"
main.xml
<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/main_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/shape.xml"
android:orientation="vertical"
android:weightSum="4">
.....................

Programmatically change colors in drawable xml file

I need to change my application's colors during runtime. I parse data file to get colors and I save it in class with static fields and methods:
public class Colors {
private static String colorOneBackground = "#00577F";
private static String colorOneForeground = "#FFFFFF";
public static void setColorOneBackground(String colorOneBackground) {
Colors.colorOneBackground = colorOneBackground;
}
public static int getColorOneForeground() {
return Color.parseColor(colorOneForeground);
}
// more colors...
Then, for example when I want to change the background of screen I do it so:
RelativeLayout relativeLayout = (RelativeLayout) myView.findViewById(R.id.loginBackground);
relativeLayout.setBackgroundColor(Colors.getColorOneBackground());
Same with textviews and other widgets. However, I have encountered one problem. Some styles are defined in Drawable folder, for example,
mybutton.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android=" http://schemas.android.com/apk/res/android "
android:shape="rectangle">
<gradient
android:startColor="#FFFFFF"
android:centerColor="#FFFFFF"
android:endColor="#FFFFFF"
android:angle="270" />
<corners android:radius="5dp" />
<stroke android:width="3px" android:color="#000000" />
</shape>
And I set this as my button's background:
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/title"
android:background="#drawable/mybutton" />
As I said I want to change these color values programatically. So I want to know if it is possible to dinamically change color values defined in xml file?
try this : to change color in your drawable xml file:
button.setBackgroundResource(R.drawable.mybutton); //drawable id
GradientDrawable gd = (GradientDrawable) button.getBackground().getCurrent();
gd.setColor(Color.parseColor("#000000")); //set color
gd.setStroke(2, Color.parseColor("#00FFFF"), 5, 6);

java.lang.ClassCastException: android.graphics.drawable.LayerDrawable cannot be cast to android.graphics.drawable.GradientDrawable

In my application I am trying change background color for each listView item. And for that I am using shapes which in layer-list.
Here is my code
drop_shadow.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<gradient android:startColor="#B7B7B7"
android:endColor="#A1A1A1"
android:angle="270"/>
<corners android:radius="10dp" />
</shape>
</item>
<item android:top="1px">
<shape android:shape="rectangle">
<solid android:color="#color/color11"/>
<corners android:radius="10dp" />
</shape>
</item>
</layer-list>
main.xml
<RelativeLayout
android:orientation="vertical"
android:id="#+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/drop_shadow"/>
When I call this method I have ClassCastException
private void setRoundedBackground(View view,int color){
GradientDrawable gradientDrawable;
gradientDrawable = (GradientDrawable) view.getBackground().mutate();
gradientDrawable.setColor(getResources().getColor(color));
gradientDrawable.invalidateSelf();
}
How could I get GradientDrawable from LayerDrawable?
you can create gradient drawable dynamically.. use below class
import android.graphics.drawable.GradientDrawable;
public class SomeDrawable extends GradientDrawable {
public SomeDrawable(int pStartColor, int pCenterColor, int pEndColor, int pStrokeWidth, int pStrokeColor, float cornerRadius) {
super(Orientation.BOTTOM_TOP,new int[]{pStartColor,pCenterColor,pEndColor});
setStroke(pStrokeWidth,pStrokeColor);
setShape(GradientDrawable.RECTANGLE);
setCornerRadius(cornerRadius);
}
}
and use this class as below
SomeDrawable drawable = new SomeDrawable(Color.parseColor("Start Color Code"),Color.parseColor("Center Color Code"),Color.parseColor("End Color Code"),1,Color.BLACK,00);
yourLayout.setBackgroundDrawable(drawable);
They are both a subclass of Drawable, so you can't cast them to each other, only to their parent classes.
i guess it's better to use separacte colors.xml file for the color of the shape, and use tag, you can delete the .
after all your shape both is the same which is rectangle.
previously i got the same error because i'm using and inside the same xml.

Get a textView background color with ShapeDrawable

I have a textview with the background defined in a xml file.
<TextView
android:id="#+id/event_tvColor"
android:layout_width="40dip"
android:layout_height="40dip"
android:text=" "
android:background="#drawable/et_style_color_service_edit"
android:clickable="true"
/>
xml file : et_style_color_service_edit.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#color/eventColor"/>
<stroke android:width="0sp" android:color="#FFFFFF" />
<size android:width="20dp"
android:height="20dp"/>
</shape>
And i need to get the color that the view have in a one time.
ShapeDrawable sc = (ShapeDrawable)tvColor.getBackground();
...............
Note that i need to use ShapeDrawable and not GradientDrawable.
Thank you for your help and time.
Solution........
Solution The xml loads into the app as a gradientdrawable and not as a shapedrawable. We have to define the shapeDrawable in java
ShapeDrawable sd = new ShapeDrawable(new RectShape);
sd.getPaint().setColor(0xFF0000FF);
if anyone have a better solution can tell.
After further research, there currently is no way of getting the xml loaded ShapeDrawable's color. What you have to do is just track your color changes so you know what color you are setting it to, ie:
int currentColor = Color.WHITE; //this is the default color (color set in xml)
public void changeColor() {
if (currentColor == Color.WHITE) {
currentColor = Color.BLUE;
} else {
currentColor = Color.WHITE;
}
GradientDrawable gd = (GradientDrawable)tvColor.getBackground();
gd.setColor(currentColor);
}

Change XML shape color while app is running

Is it possible to change rectangle (drawn in xml) color in Java code while app is running?
My rectangle.xml:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="#+id/listview_background_shape">
<stroke android:width="2dp" android:color="#ffffff" />
<padding android:left="20dp"
android:top="20dp"
android:right="20dp"
android:bottom="20dp" />
<solid android:color="#006600" />
</shape>
Drawn in main.xml by:
<View
android:id="#+id/myRectangleView"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:background="#drawable/rectangle"/>
I've tried this way:
GradientDrawable sd;
View viewrectangle;
viewrectangle = (View) findViewById(R.id.myRectangleView);
sd = (GradientDrawable) viewrectangle.getBackground();
sd.setColor(0xffffff00);
sd.invalidateSelf();
It only works when I put it inside OnCreate method.
I want to change rect color by a button, so I put this code inside button's onClick() method. But when I click button while app is running color doesn't change. Any suggestions?
Used this code and it worked, alternatively consider redrawing the viewrectangle using viewrectangle.invalidate(), but it shouldn't be nescarry:
View viewrectangle;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
viewrectangle = (View) findViewById(R.id.myRectangleView);
}
public void doClick(View v) {
GradientDrawable sd = (GradientDrawable) viewrectangle.getBackground();
sd.setColor(0xffffff00);
sd.invalidateSelf();
}
In this example the "doClick()" method is set in the main.xml:
<Button android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="Button"
android:onClick="doClick"/>
You can put this code in a separate method, and that method you can call from onClick of button..
You could try a color filter. I've used it before to change the color of buttons (note that they started out as standard gray), if you start with another color it could be a very different outcome. Anyway, an example of how I did it:
Import the PorterDuff graphics stuff:
import android.graphics.PorterDuff;
In the class define the item you want to color filter and set the filter:
Button atdButton = (Button) convertView.findViewById(R.id.attendbutton);
if (atdState[position].equals("P")) {
atdButton.getBackground().setColorFilter(0xFF00FF00, // Set filter to green
PorterDuff.Mode.MULTIPLY);
} else if (atdState[position].equals("T")) {
atdButton.getBackground().setColorFilter(0xFFFFFF00, // Set filter to yellow
PorterDuff.Mode.MULTIPLY);
} else if (atdState[position].equals("E")) {
atdButton.getBackground().setColorFilter(0xFFFF6600, // Set filter to orange
PorterDuff.Mode.MULTIPLY);
} else if (atdState[position].equals("U")) {
atdButton.getBackground().setColorFilter(0xFFFF0000, // Set filter to red
PorterDuff.Mode.MULTIPLY);
} else {
atdButton.getBackground().clearColorFilter();
}

Categories

Resources