I make a android application with a button where in there a total of 4 texts and I want to align the first 2. One at the most left side of the bottom text and the other and the right side of the bottom text.
So from this:
setText(item.title + " " + item.roomId + "\n" + item.teacher + " "
+ item.classes);
To this:
setText(declare here a spannable);
I think I should work with Spannable, I've tried some things with Alignment.ALIGN_NORMAL
and Alignment.ALIGN_OPPOSITE
but I think is should first calculate the length of the bottom text and then do the alignment. (I've found a good example here but it's not working in my set-up).
I hope that someone can point me to a good direction.
Edit:
The reason that I can not (I think) use RelativeLayout
or LinearLayout
is that I'm extending button in a different class (ScheduleItemView.java
):
/**
* Custom view that represents a {@link ScheduleItem} instance, including its
* title and time span that it occupies. Usually organized automatically by
* {@link ScheduleItemsLayout} to match up against a {@link TimeRulerView}
* instance.
*/
public class ScheduleItemView extends Button {
private ScheduleItem mItem;
public ScheduleItemView(Context context, ScheduleItem item) {
super(context);
mItem = item;
setSingleLine(false);
setText(item.title + " " + item.roomId + "\n" + item.teacher + " "
+ item.classes);
// TODO: turn into color state list with layers?
int textColor = Color.WHITE;
int accentColor = item.accentColor;
LayerDrawable buttonDrawable = (LayerDrawable) context.getResources()
.getDrawable(R.drawable.btn_block);
buttonDrawable.getDrawable(0).setColorFilter(accentColor,
PorterDuff.Mode.SRC_ATOP);
buttonDrawable.getDrawable(1).setAlpha(item.containsStarred ? 255 : 0);
setTextColor(textColor);
setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources()
.getDimensionPixelSize(R.dimen.text_size_small));
setGravity(Gravity.CENTER | Gravity.BOTTOM);
setBackgroundDrawable(buttonDrawable);
}
public ScheduleItem getScheduleItem() {
return mItem;
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(),
MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
getMeasuredHeight(), MeasureSpec.EXACTLY));
// layout(getLeft(), getTop(), getRight(), getBottom());
setGravity(Gravity.CENTER);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getRight() - getLeft(), getBottom() - getTop());
}
}
I've tried to do this in protected void onLayout
(ScheduleItemsLayout.java
):
child.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
But that's not working. I'm not sure if I should use new RelativeLayout(this)
.
Is it better to use Spannable
in this case?
The source of the project can be downloaded here (which you can import in Eclipse)
Well, if you can't make the move from Button
to a ViewGroup
, here's what you can do in your extended Button class:
Remove:
setText(item.title + " " + item.roomId + "\n" + item.teacher + " "
+ item.classes);
Add the following to ScheduleItemView's
constructor:
float[] fl1 = new float[item.title.length()];
getPaint().getTextWidths(item.title, fl1);
float[] fl2 = new float[item.roomId.length()];
getPaint().getTextWidths(item.roomId, fl2);
float[] fl3 = new float[item.teacher.length() + item.classes.length() + 1];
getPaint().getTextWidths(item.teacher + " " + item.classes, fl3);
float differenceInWidth = sumUpTheArray(fl3)
- sumUpTheArray(fl1)
- sumUpTheArray(fl2);
float fSpaceArray[] = new float[1];
getPaint().getTextWidths(" ", fSpaceArray);
int numOfSpaces = (int) (differenceInWidth / fSpaceArray[0]);
char[] spaceCharArr = new char[numOfSpaces];
Arrays.fill(spaceCharArr, ' ');
setText(item.title + String.valueOf(spaceCharArr) + item.roomId + "\n"
+ item.teacher + " " + item.classes);
Add this helper method which sums up a float
array:
public float sumUpTheArray(float[] arr) {
float sum = 0f;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
Not sure why you're overriding the onDraw(Canvas)
and onMeasure(int, int)
methods.
Needless to say, this is one convoluted code snippet. What's happening is that we're measuring how much space we must put between title
and roomId
to get the desired alignment. The code is straight-forward (though cringe-worthy), so no comments have been included.
On the other hand, you could extend RelativeLayout:
public class ScheduleItemAlternateView extends RelativeLayout {
private ScheduleItem mItem;
public ScheduleItemAlternateView(Context context, ScheduleItem item) {
super(context);
mItem = item;
int textColor = Color.WHITE;
int accentColor = item.accentColor;
LayerDrawable buttonDrawable = (LayerDrawable) context.getResources()
.getDrawable(R.drawable.btn_block);
buttonDrawable.getDrawable(0).setColorFilter(accentColor,
PorterDuff.Mode.SRC_ATOP);
buttonDrawable.getDrawable(1).setAlpha(item.containsStarred ? 255 : 0);
// Three TextViews to hold the `title`, `roomId`
// and `teacher&room` independently
TextView tvTitle = new TextView(context);
TextView tvRoomId = new TextView(context);
TextView tvTeacherAndClasses = new TextView(context);
// Example ids
tvTitle.setId(100);
tvRoomId.setId(101);
tvTeacherAndClasses.setId(102);
tvTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources()
.getDimensionPixelSize(R.dimen.text_size_small));
tvRoomId.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources()
.getDimensionPixelSize(R.dimen.text_size_small));
tvTeacherAndClasses.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources()
.getDimensionPixelSize(R.dimen.text_size_small));
tvTitle.setPadding(30, 20, 30, 0);
tvRoomId.setPadding(30, 20, 30, 0);
tvTeacherAndClasses.setPadding(30, 5, 30, 20);
tvTitle.setTextColor(textColor);
tvRoomId.setTextColor(textColor);
tvTeacherAndClasses.setTextColor(textColor);
// Set text
tvTitle.setText(item.title);
tvRoomId.setText(item.roomId);
tvTeacherAndClasses.setText(item.teacher + " " + item.classes);
// LayoutParms
RelativeLayout.LayoutParams paramsTitle =
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
paramsTitle.addRule(RelativeLayout.ALIGN_LEFT,
tvTeacherAndClasses.getId());
RelativeLayout.LayoutParams paramsRoomId =
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
paramsRoomId.addRule(RelativeLayout.ALIGN_RIGHT,
tvTeacherAndClasses.getId());
RelativeLayout.LayoutParams paramsTeacherAndClasses =
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
paramsTeacherAndClasses.addRule(RelativeLayout.CENTER_HORIZONTAL);
paramsTeacherAndClasses.addRule(RelativeLayout.BELOW, tvTitle.getId());
// Add Views to this RelativeLayout
addView(tvTitle, paramsTitle);
addView(tvRoomId, paramsRoomId);
addView(tvTeacherAndClasses, paramsTeacherAndClasses);
// Set the background as LayerDrawable
setBackgroundDrawable(buttonDrawable);
}
}
Here, we create three TextViews, and set their LayoutParams to get proper alignment.
Output is the same for both, though I would recommend the second approach:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With