How to center text in custom "square" TextView - android

I've create a custom TextView because I want:
its height to match certain constraints (top to top and bottom to bottom of another TextView)
its width matching that height so the oval shape xml set as background of the TextView shows a circle.
Here's the code of the custom View:
public class SquareTextView extends AppCompatTextView {
public static final String TAG = "SquareTextView";
int squareDim = 0;
public SquareTextView(Context context) {
super(context);
}
public SquareTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int h = this.getMeasuredHeight();
int w = this.getMeasuredWidth();
squareDim = Math.max(w, h);
setMeasuredDimension(squareDim, squareDim);
}
}
layout xml:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tv_registration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="16dp"
android:text="WW-WWW"
android:textAppearance="#style/TextAppearance.AppCompat.Large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/tv_aircraft_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MMMMMMMMM"
android:textAppearance="#style/TextAppearance.AppCompat.Medium"
app:layout_constraintStart_toStartOf="#+id/tv_registration"
app:layout_constraintTop_toBottomOf="#+id/tv_registration" />
<com.mydomain.SquareTextView
android:id="#+id/tv_counter"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginEnd="24dp"
android:background="#drawable/shape_circle"
android:gravity="center"
android:text="0"
android:textAlignment="center"
android:textAppearance="#style/TextAppearance.AppCompat.Large"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#+id/tv_registration"
app:layout_constraintBottom_toTopOf="#+id/cv_ops_restrictions"/>
</android.support.constraint.ConstraintLayout>
</ScrollView>
shape_circle.xml:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" >
<size android:width="50dp"
android:height="50dp"/>
<solid android:color="#android:color/white"/>
</shape>
Problem is that I want the text centered in the circle. Any pointers on how to achieve this or on what I'm doing wrong? at the moment it looks like this:

I'd like to recommend that you don't use a custom TextView subclass at all here. You're already working inside ConstraintLayout, which supports aspect ratios for its children. That means you can replace <com.mydomain.SquareTextView> with <TextView> and add this attribute to get a perfect square view:
app:layout_constraintDimensionRatio="1:1"

Related

How Can I create a Circular CardView in Android?

i'm trying to create a circular CardView. But I don't know how to do it. Is there any attribute with which I can get a Circular CardView?.
The XML code is the following:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view_outer"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_gravity="center"
card_view:cardBackgroundColor="#android:color/transparent"
card_view:cardCornerRadius="0dp"
card_view:cardElevation="3dp" >
</android.support.v7.widget.CardView>
Just use the shapeAppearanceOverlay attribute:
<com.google.android.material.card.MaterialCardView
android:layout_width="100dp"
android:layout_height="100dp"
app:cardBackgroundColor="#color/colorPrimaryLight"
app:shapeAppearanceOverlay="#style/circle"
/>
with:
<style name="circle">
<item name="cornerSize">50%</item>
</style>
<androidx.cardview.widget.CardView
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_margin="10dp"
app:cardCornerRadius="100dp"/>
May be changing app:cardCornerRadius to half of the width and height.
OR
May be Custom CardView
public class CircularCardView extends CardView {
public CircularCardView(#NonNull Context context) {
super(context);
}
public CircularCardView(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public CircularCardView(#NonNull Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
setMeasuredDimension(width, width);
setRadius(width/2);
}
}
XML
<com.yourpackage.name.CircularCardView
android:layout_width="50dp"
android:layout_height="100dp"
android:layout_margin="10dp"
app:cardElevation="10dp"
/>
I wanted to have a circular image So did something like this
<androidx.cardview.widget.CardView
android:id="#+id/roundCardView"
android:layout_width="100dp"
android:layout_height="100dp"
android:elevation="0dp"
app:cardCornerRadius="10dp"
app:layout_constraintTop_toTopOf="#id/userName"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="20dp">
<ImageView
android:id="#+id/profilePic"
android:layout_width="100dp"
android:layout_height="100dp" />
</androidx.cardview.widget.CardView>
Its better if you migrate to androidx but you can use this code add shape to your card view
<app:android.support.v7.widget.CardView
android:layout_width="150dp"
android:layout_height="148dp"
android:elevation="12dp"
app:cardCornerRadius="75dp"
android:layout_centerHorizontal="true"
android:innerRadius="40dp"
android:shape="ring"
android:thicknessRatio="4">
</app:android.support.v7.widget.CardView>
This worked for me for all Android Versions
<androidx.cardview.widget.CardView
android:layout_width="90dp"
android:layout_height="90dp"
app:cardCornerRadius="45dp"
android:shape="ring"
app:cardElevation="5dp">

RecyclerView item with GridLayoutManager shows different view positions

I have recycler view which uses grid layout manager to show items in 2 columns like this:
If you notice the image bottom margin is different for left row. In the item layout the image view has property "alignparentbottom=true", but all the items in the left row have this wrong margin at bottom (png file has no margin, I have verified.). I have extended RelativeLayout to make it square shaped like this:
public class SquareRelativeLayout extends RelativeLayout {
private static final int HEIGHT_RATIO = 1;
private static final int WIDTH_RATIO = 1;
public SquareRelativeLayout(Context context) {
super(context);
}
public SquareRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SquareRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Set a square layout.
/*int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = (int) (HEIGHT_RATIO / WIDTH_RATIO * widthSize);
int newHeightSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);*/
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}
Here is the whole item layout:
<?xml version="1.0" encoding="utf-8"?>
<com.org.framework.ui.widget.SquareRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rl_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/transparent_round_rect"
android:layout_marginTop="#dimen/margin_16" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/ll_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="20"
android:layout_marginTop="#dimen/margin_12"
android:layout_marginRight="#dimen/margin_12"
android:layout_marginLeft="#dimen/margin_12">
<TextView
android:id="#+id/tv_wallet_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="15"
style="#style/SmallWhiteText"
android:text="Reimbursement"
android:ellipsize="end"
android:lines="1"
android:maxLines="1" />
<RadioButton
android:id="#+id/rb_select"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="5"
android:layout_marginTop="-3dp"
android:layout_gravity="end|center_vertical"
android:buttonTint="#color/white" />
</LinearLayout>
<TextView
android:id="#+id/tv_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="#style/LargeWhiteText"
android:text="2000"
android:layout_marginRight="#dimen/margin_12"
android:layout_marginLeft="#dimen/margin_12"
android:layout_below="#id/ll_top"/>
<ImageView
android:id="#+id/iv_wallet_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/gift"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
/>
<!--android:layout_marginRight="-1.5dp"
android:layout_marginBottom="-7dp"-->
<FrameLayout
android:id="#+id/fl_na"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#435977"
android:layout_alignParentBottom="true"
android:padding="5dp"
android:visibility="gone">
<TextView
android:id="#+id/tv_not_applicable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/text_not_applicable"
style="#style/VerySmallWhiteText"
android:layout_gravity="center_horizontal"/>
</FrameLayout>
</RelativeLayout>
</com.org.framework.ui.widget.SquareRelativeLayout>
First- Items shouldn't have different bottom margins for left and right columns. What's the reason?
second- I have tried to programatically fix the layout inside onBindViewHolder method (with/without layout tree observer) like this:
ViewTreeObserver tob = uvh.rlRoot.getViewTreeObserver();
tob.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
uvh.rlRoot.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Log.e("flNa", (uvh.flNa.getTop()+uvh.flNa.getHeight())+",");
Log.e("ivWallet", (uvh.ivLogo.getTop()+uvh.ivLogo.getHeight())+",");
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) uvh.ivLogo.getLayoutParams();
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
//params.bottomMargin = 0;
//uvh.ivLogo.setBottom(-10);
uvh.ivLogo.setTop(uvh.rlRoot.getHeight()-uvh.ivLogo.getHeight());
uvh.ivLogo.setLayoutParams(params);
RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) uvh.flNa.getLayoutParams();
params1.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
params1.bottomMargin = 1;
uvh.flNa.setLayoutParams(params1);
uvh.rlRoot.forceLayout();
uvh.rlRoot.invalidate();
uvh.rlRoot.requestLayout();
}
});
This has no effect on layout.
How to fix this issue?

How to make fix height on items in GridLayoutManager?

I'm making some grid with image and text, using GridLayoutManager. But currently my items have different height if on one row text is on one line and on the second row text has two lines, which don't looks good. How to make all items equals to each other (best option if every item height will be equal to max element height
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#color/white"
android:layout_margin="1dp">
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textAlignment="center"
tools:text="Long title long title long title(560)" />
</RelativeLayout>
</LinearLayout>
Try below code may work for you, where I have created custom relative layout
package com.test;
public class MySquareRelativeLayout extends RelativeLayout {
public MySquareRelativeLayout(Context context) {
super(context);
}
public MySquareRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MySquareRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(VERSION_CODES.LOLLIPOP)
public MySquareRelativeLayout(Context context, AttributeSet attrs,int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Set a square layout.
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}
<?xml version="1.0" encoding="utf-8"?>
<com.test.MySquareRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/elementRootView"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/image"
android:textAlignment="center"
tools:text="Long title long title long title(560)" />
</com.test.MySquareRelativeLayout>

How to set width to ImageView in ListView for mutil screen

I have a ListView with an ImageView and TextView, I want to set the width of the image as 2/3 of the screen.
How do I create a custom ImageView to do this? This is what I've tried so far.
Custom View
public class CustomImageListView extends ImageView {
public CustomImageListView(Context context) {
super(context);
}
public CustomImageListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomImageListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Snap
// to
int width = MainActivity.width;
int height = MainActivity.height;
int w = width *2/5;
int h = w *4/6;
setMeasuredDimension(w, h);
// setMeasuredDimension(ChoseImage.width, ChoseImage.height); // Snap to
// //
// width
}
}
The custom View XML
<tuannt.tinmoi.custom.CustomImageListView
android:id="#+id/ivAvater"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/nomage" />
You can define a horizontal linear layout with WeightSum = 3 and inside it put another layout with with layout_weight = 1, the remaining portion will be of weight = 2, so you can put your imageView there. Refer below:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/fullscreen"
style="#style/translucent"
android:orientation="horizontal"
android:weightSum="3">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_gravity="right"
android:gravity="center"
android:background="#88000000"
android:id="#+id/sidebar"
android:layout_weight="1" >
</RelativeLayout>
<!-- other views, with a total layout_weight of 2 -->
</LinearLayout>
You don't need to create a Custom View to achieve this. You can make use of the layout_weight attribute.
This would be your layout for every item in the ListView.
item_in_listview.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
The layout_weight attribute is explained in this question.
In a nutshell, layout_weight specifies how much of the extra space in
the layout to be allocated to the View.

Android circle background becomes oval

I want to put a circle background on a textview. The circle becomes oval when its rendered.
My layout XML:
<TextView
android:id="#+id/amount_key"
android:layout_weight="1"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_marginRight="2dp"
android:gravity="center"
android:background="#drawable/circle"
android:layout_marginLeft="20dp"
android:text="3\ndays"
android:padding="20dp"
android:textColor="#ffffff"
android:textStyle="bold"
android:textSize="25dp" />
</LinearLayout>
My circle background:
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="#79bfea"/>
</shape>
Change your textView's layout_height and layout_width to wrap_content
Add size tag inside shape tag as follows
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">>
<solid android:color="#79bfea" />
<size android:height="25dp"
android:width="25dp"/>
</shape>
If it is still oval, try increasing the width and height in size tag. It worked for me!
You can create your own Drawable which will constrain the radius to the min value between its width and height.
package com.example.android;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
public class ColorCircleDrawable extends Drawable {
private final Paint mPaint;
private int mRadius = 0;
public ColorCircleDrawable(final int color) {
this.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
this.mPaint.setColor(color);
}
#Override
public void draw(final Canvas canvas) {
final Rect bounds = getBounds();
canvas.drawCircle(bounds.centerX(), bounds.centerY(), mRadius, mPaint);
}
#Override
protected void onBoundsChange(final Rect bounds) {
super.onBoundsChange(bounds);
mRadius = Math.min(bounds.width(), bounds.height()) / 2;
}
#Override
public void setAlpha(final int alpha) {
mPaint.setAlpha(alpha);
}
#Override
public void setColorFilter(final ColorFilter cf) {
mPaint.setColorFilter(cf);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
then apply to your textView:
textView.setBackground(new ColorCircleDrawable(Color.RED));
To get this
I used two LinearLayout inside each other and set parent gravity to CENTER
<LinearLayout
android:layout_width="80dp"
android:layout_height="50dp"
android:baselineAligned="false"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="45dp"
android:layout_height="45dp"
android:gravity="center"
android:background="#drawable/oval"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Text"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
and this is oval.xml inside drawable folder
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#393939" />
<size
android:width="40dp"
android:height="40dp" />
</shape>
without inner LinearLayout you'll get this
which it's code is
<LinearLayout
android:layout_width="80dp"
android:layout_height="50dp"
android:baselineAligned="false"
android:gravity="center"
android:background="#drawable/oval"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Text"
android:textSize="12sp" />
</LinearLayout>
I extended TextView class to set width as height
public class TextViewSquareShaped extends TextView {
public TextViewSquareShaped(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public TextViewSquareShaped(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public TextViewSquareShaped(Context context) {
super(context);
init(null);
}
private void init(AttributeSet attrs) {
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
setMeasuredDimension(width, width);
Log.v("measure", "width:" + width + " height:" + width);
}
}
And then combined with above Sudhasri's answer, I can show exact circular text view.
So no need to give fixed height and weight.
Since you are using match_parent for width and height and setting drawable in background, so it will be oval. To achieve circle you can give same dimensions for width and height. NA dif want full screen then you can width from java code using WindowManager and set the same value in both width and height.
try ring instead of oval
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring" >
<solid android:color="#79bfea" />
</shape>

Categories

Resources