Align Top of Image to Top of Textview

Align top of image to top of TextView

You can align a compound-Drawable to the top (or bottom) by creating a custom Drawable that wraps your Drawable, and then manipulate the drawing of your custom Drawable by overriding the method onDraw(Canvas).

The sample below is the simplest possible example. This aligns the image to the top, but you can also make it align to the bottom, left or right of the TextView by implementing the required logic in the onDraw(Canvas)-method. You might also want to build in a margin in the onDraw(Canvas), to make your design implementation pixel perfect.

Sample usage:

GravityCompoundDrawable gravityDrawable = new GravityCompoundDrawable(innerDrawable);
// NOTE: next 2 lines are important!
innerDrawable.setBounds(0, 0, innerDrawable.getIntrinsicWidth(), innerDrawable.getIntrinsicHeight());
gravityDrawable.setBounds(0, 0, innerDrawable.getIntrinsicWidth(), innerDrawable.getIntrinsicHeight());
mTextView.setCompoundDrawables(gravityDrawable, null, null, null);

Sample code:

public class GravityCompoundDrawable extends Drawable {

// inner Drawable
private final Drawable mDrawable;

public GravityCompoundDrawable(Drawable drawable) {
mDrawable = drawable;
}

@Override
public int getIntrinsicWidth() {
return mDrawable.getIntrinsicWidth();
}

@Override
public int getIntrinsicHeight() {
return mDrawable.getIntrinsicHeight();
}

@Override
public void draw(Canvas canvas) {
int halfCanvas= canvas.getHeight() / 2;
int halfDrawable = mDrawable.getIntrinsicHeight() / 2;

// align to top
canvas.save();
canvas.translate(0, -halfCanvas + halfDrawable);
mDrawable.draw(canvas);
canvas.restore();
}
}

Text TOP Right on Image in Android

Give a marginTop to the imageview and then give the half of that as the marginTop of the textview.

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layoutforprofileimage"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
android:id="@+id/image"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_marginTop="20dp"
android:padding="2dp"
android:src="@drawable/user" />

<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="@id/image"
android:layout_marginRight="0dp"
android:layout_marginTop="10dp"
android:adjustViewBounds="true"
android:background="@drawable/tv_circle"
android:gravity="center"
android:minHeight="20sp"
android:minWidth="20sp"
android:padding="2dp"
android:paddingBottom="1dp"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:scaleType="fitStart"
android:text="0"
android:textColor="#ffffffff"
android:textSize="12sp"
android:visibility="visible"
tools:ignore="RtlHardcoded" />

tv_circle.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">

<solid android:color="#F08600" />

<padding
android:left="1dp"
android:right="1dp"
android:top="1dp" />

</shape>

For the above XML the output will be as following screenshot.

Sample Image

Align View to the top of a rotated TextView

I found two solutions:

  • Solution 1

Writing a simple custom control that inherits from TextView:

public class VerticalTextView extends TextView {
final boolean topDown;

public VerticalTextView(Context context,
AttributeSet attrs) {
super(context, attrs);
final int gravity = getGravity();
if (Gravity.isVertical(gravity) && (gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
setGravity( (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP );
topDown = false;
} else {
topDown = true;
}
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}

@Override
protected void onDraw(Canvas canvas) {
if (topDown) {
canvas.translate(getWidth(), 0);
canvas.rotate(90);
} else {
canvas.translate(0, getHeight());
canvas.rotate(-90);
}

canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
getLayout().draw(canvas);
}
}
  • Solution 2

Usint this library. How to use?

Add in your dependencies in build.gradle file:

dependencies {
compile 'rongi.rotate-layout:rotate-layout:2.0.0'
}

XML file:


<com.github.rongi.rotate_layout.layout.RotateLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:angle="270"> <!-- Specify rotate angle here -->

<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="50sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</com.github.rongi.rotate_layout.layout.RotateLayout>

<Button
android:layout_width="200dp"
android:layout_height="64dp"
android:text="Align me!"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/text"/>

How could I align the drawableLeft icon to the top

The reason why the "dot" is drawn twice is because you call super.onDraw(canvas). You've drawn the dot yourself in the top-position, and then you let the system draw the dot on the original position by calling the super.

Unfortunately, you have to call super.onDraw(canvas) in order to draw the text. A better approach to achieve what you want is by creating a custom Drawable that wraps the Drawable you want to display, and then override the draw(Canvas) method of the custom Drawable.

See my answer here for an example. The only downside is that you have to set the drawableLeft from code, not XML.



Related Topics



Leave a reply



Submit