TextView with rounded background - java

I'm making a messenger application i made for every message a background with this shape:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners
android:bottomLeftRadius="80dp"
android:bottomRightRadius="80dp"
android:topRightRadius="80dp"
android:topLeftRadius="80dp"
/>
<solid android:color="#fff"/>
But the problem is when the message is long the corners be big and this make my message layout is bad! i want to know if there's another method to make a rounded background!

You can use 9-patch drawables.
These are png files whose allow you to define areas that can't be stretched and areas that will stay same size regardless the view size.
You can read about it here:
https://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch
You can read about how to create it here:
https://developer.android.com/studio/write/draw9patch.html
9-patch drawables are commonly used in Adnroid SDK Standard views.

You can create a custom button class which extend Button class and then override the onLayout() method may be like this... where basically you are setting the corner radius = height/2
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if(this.getBackground()!=null && this.getBackground() instanceof LayerDrawable) {
LayerDrawable layerDrawable = (LayerDrawable)(this.getBackground().mutate());
GradientDrawable gd1 = (GradientDrawable)layerDrawable.findDrawableByLayerId(R.id.layer_one);
roundEdgeGradientDrawable(gd1, this.getHeight());
}
}
public static GradientDrawable roundEdgeGradientDrawable(GradientDrawable bgShape, float height) {
if (bgShape != null) {
float radius = height / 2;
float[] radii = {radius, radius, radius, radius, radius, radius, radius, radius};
bgShape.setCornerRadii(radii);
}
return bgShape;
}

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#color/headerColor" />
<corners android:radius="5dp" />
</shape>

Related

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!!))
}

Bitmap inside white circle

I'm trying to fill Bitmap inside white circle, more specifically:
I've a Bitmap for example this:
And I want this:
I've make background gray for understand image.
I use this method, but it doesn't make what I want..
public static Bitmap getRoundedBitmap(Bitmap bitmap)
{
final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(output);
final int color = Color.WHITE;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawOval(rectF, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
bitmap.recycle();
return output;
}
I guess the color you use to paint the oval has ALPHA = 0. Try replacing Color.WHITE with Color(1.0f, 1.0f, 1.0f, 1.0f). Tell me if that solved your problem, and take a look at:
What does PorterDuff.Mode mean in android graphics.What does it do?
In this case, for SRC_IN: [Sa * Da, Sc * Da] (Taken from android reference, PorterDuff.Mode)
Here's an example that uses a shape made in XML.
1) Right-click on your drawable resource folder and create a new Drawable resource file.
2) Paste the following code. This creates a drawable resource which has a pretty similar look to the background that you wanted.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<size android:width="50dp" android:height="50dp"/>
<solid android:color="#android:color/darker_gray"/>
</shape>
</item>
<item>
<shape android:shape="oval">
<size android:width="50dp" android:height="50dp"/>
<solid android:color="#android:color/white"/>
</shape>
</item>
</layer-list>
3) Use the resource in your layout. Substitute my placeholder Android checkbox with your 'tick' resource file.
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/highlight_circle">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="#android:drawable/checkbox_on_background"/>
</RelativeLayout>

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);

Java/Android rounded drawable/bitmap - 4 diffrent radiuses and size

I searched but not found any clue to help my problem:
I have an ImageView with some layer drawable that presents border radiuses to that view. Also I set jpg/png file that should present its background(and should be more like css equivalent to code shortly like 'background-image:url(....)'),
My main issue is that when jpg/png file is small theres a problem that it is first cornered, and then stretched, and cause of result image looks more like circle, not like stretched rectangle with rounded corners.
Important note:I have 4 different corner-radiuses(any number from 0 to 1000), like in web radius-top-left,radius-top-right, etc.
Anyone had problem like that or know better way of implementing this?
I tried to add use custom drawable:
public class RoundCornersBitmap extends PaintDrawable {
private Bitmap mBitmap;
private final Paint mPaint;
private final BitmapShader mShader;
private final ImageView mView;
public RoundCornersBitmap(Bitmap bmp, ImageView view) {
mBitmap = bmp;
mPaint = new Paint();
mShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPaint.setShader(mShader);
mPaint.setFlags(Paint.FILTER_BITMAP_FLAG);
mView = view;
//example corners
this.setCornerRadii(new float[]{50, 50, 120, 120, 90, 90, 40, 40});
}
#Override
public int getIntrinsicWidth() {
return mBitmap.getWidth();
}
#Override
public int getIntrinsicHeight() {
return mBitmap.getHeight();
}
#Override
public Paint getPaint() {
return mPaint;
}
#Override
public void draw(Canvas canvas) {
getShape().draw(canvas, mPaint);
}
}
and my with layer list presents as folowing:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#ff00ff"></solid>
<corners android:topLeftRadius="50px" android:topRightRadius="120px"
android:bottomLeftRadius="90px"
android:bottomRightRadius="40px"></corners>
<padding android:top="20px" android:left="20px" android:right="20px" android:bottom="20px"></padding>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#f0000f"></solid>
<corners android:topLeftRadius="50px" android:topRightRadius="120px"
android:bottomLeftRadius="90px"
android:bottomRightRadius="40px"></corners>
<padding android:top="1px" android:bottom="1px" android:left="1px" android:right="1px"></padding>
</shape>
</item>
</layer-list>
addinationaly my layout.xml presents like that:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ImageView
android:id="#+id/sk"
android:layout_width="320px"
android:layout_height="380px"
android:background="#drawable/skdrawable"
android:src="#drawable/ski2"
android:scaleType="fitCenter"
/>
</LinearLayout>
also code in my activity that should do the task:
ImageView view = (ImageView) findViewById(R.id.sk);
BitmapDrawable d = (BitmapDrawable) getResources().getDrawable(R.drawable.ski2);
view.setImageDrawable(new RoundCornersBitmap(d.getBitmap(),view));
I'd appreciate any help .
I found workaround with using extra path in my imageview:
Rect outRect = new Rect();
getDrawingRect(outRect);
mPath.addRoundRect(new RectF(outRect.left,outRect.top, width,height), floats_array, Path.Direction.CW);
and clipping it in onDraw:
canvas.clipPath(mPath);

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