i have a screen filled with buttons in my app and i need to have three specific buttons to turn 90 degree so their text will be turned i tried to use
android:rotation="90"
it fixed my text direction problem but it made it so the button be too small (the button kept their width size)
i need it will look like this
for this three button i need to change (the button that said 1st12 2st12 and 3st12) is:
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="20sp"
android:textStyle="bold"
android:text="1st12"
android:rotation="90"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="20sp"
android:text="2st12"
android:rotation="90"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="20sp"
android:text="3st12"
android:rotation="90"/>
any help will be great thanks
You can custom 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 boolean setFrame(int l, int t, int r, int b){
return super.setFrame(l, t, l+(b-t), t+(r-l));
}
#Override
public void draw(Canvas canvas){
if(topDown){
canvas.translate(getHeight(), 0);
canvas.rotate(90);
}else {
canvas.translate(0, getWidth());
canvas.rotate(-90);
}
canvas.clipRect(0, 0, getWidth(), getHeight(), android.graphics.Region.Op.REPLACE);
super.draw(canvas);
}
}
Related
I have a textView which I want to remove every padding and extra space at the top and bottom of the text. This is my XML:
<TextView
android:id="#+id/stid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/quicksand"
android:gravity="center_horizontal"
android:includeFontPadding="false"
android:maxLines="1"
android:text="#string/st"
android:textSize="40sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.538"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
I am wrapping content and removing font padding but there is still a large padding at the top and at the bottom of the text which I want to remove. (on the sides it is fine just top and bottom)
this is a screenshot as requested
Did you try?
android:includeFontPadding="false"
android:lineSpacingExtra="-5dp"
Use this class and compile your project.
public class NoPaddingTextView extends TextView {
private int mAdditionalPadding;
public NoPaddingTextView(Context context) {
super(context);
init();
}
public NoPaddingTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setIncludeFontPadding(false);
}
#Override
protected void onDraw(Canvas canvas) {
int yOff = -mAdditionalPadding / 6;
canvas.translate(0, yOff);
super.onDraw(canvas);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
getAdditionalPadding();
int mode = MeasureSpec.getMode(heightMeasureSpec);
if (mode != MeasureSpec.EXACTLY) {
int measureHeight = measureHeight(getText().toString(), widthMeasureSpec);
int height = measureHeight - mAdditionalPadding;
height += getPaddingTop() + getPaddingBottom();
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private int measureHeight(String text, int widthMeasureSpec) {
float textSize = getTextSize();
TextView textView = new TextView(getContext());
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
textView.setText(text);
textView.measure(widthMeasureSpec, 0);
return textView.getMeasuredHeight();
}
private int getAdditionalPadding() {
float textSize = getTextSize();
TextView textView = new TextView(getContext());
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
textView.setLines(1);
textView.measure(0, 0);
int measuredHeight = textView.getMeasuredHeight();
if (measuredHeight - textSize > 0) {
mAdditionalPadding = (int) (measuredHeight - textSize);
Log.v("NoPaddingTextView", "onMeasure: height=" + measuredHeight + " textSize=" + textSize + " mAdditionalPadding=" + mAdditionalPadding);
}
return mAdditionalPadding;
}
}
Replace TextView with NoPaddingTextView Class Name in your XML file
<YourPackage.NoPaddingTextView
android:id="#+id/stid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/quicksand"
android:gravity="center_horizontal"
android:includeFontPadding="false"
android:maxLines="1"
android:text="#string/st"
android:textSize="40sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.538"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Source : Github
StackOverFlow
This question already has answers here:
Put constant text inside EditText which should be non-editable - Android
(18 answers)
Closed 6 years ago.
I want an EditText which displays a fixed text, something like display below.
try this one
<?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">
<EditText
android:id="#+id/editText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:text="IN +91"/>
<EditText
android:id="#+id/editText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="10dp"
android:inputType="textPersonName"
android:hint="Enter mobile number here"/>
</LinearLayout>
Refer this https://medium.com/#ali.muzaffar/adding-a-prefix-to-an-edittext-2a17a62c77e1#.y6uxyppam
public class PrefixEditText extends AppCompatEditText {
float mOriginalLeftPadding = -1;
public PrefixEditText(Context context) {
super(context);
}
public PrefixEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PrefixEditText(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
calculatePrefix();
}
private void calculatePrefix() {
if (mOriginalLeftPadding == -1) {
String prefix = (String) getTag();
float[] widths = new float[prefix.length()];
getPaint().getTextWidths(prefix, widths);
float textWidth = 0;
for (float w : widths) {
textWidth += w;
}
mOriginalLeftPadding = getCompoundPaddingLeft();
setPadding((int) (textWidth + mOriginalLeftPadding),
getPaddingRight(), getPaddingTop(),
getPaddingBottom());
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
String prefix = (String) getTag();
canvas.drawText(prefix, mOriginalLeftPadding,
getLineBounds(0, null), getPaint());
}
}
Usage:
<com.alimuzaffar.customwidgets.PrefixEditText
fontPath="fonts/Lato-Light.ttf"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
android:textSize="24sp"
android:tag="+61 "
android:text="1234" />
OR
android-phone-number-with-flags
[https://github.com/dlukashev/android-phone-number-with-flags
I am making an application in Android and I am currently trying to make a vertical TextView. I want it to look similar to this.
Does anyone know how to achieve this, or at least an existing library which I can use to get this effect.
Thanks
If you want vertical Text View like this then you need to pass \n to Text View text property.
Refer this.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/description"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:background="#000"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="5dp"
android:text="A\nB\nC\nD\n"
android:textColor="#FFF"
android:textSize="18dp" />
</RelativeLayout>
You must create custom view
For example:
public class VerticalTextView extends AppCompatTextView {
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 boolean setFrame(int l, int t, int r, int b) {
return super.setFrame(l, t, l + (b - t), t + (r - l));
}
#Override
public void draw(Canvas canvas) {
if (topDown) {
canvas.translate(getHeight(), 0);
canvas.rotate(90);
} else {
canvas.translate(0, getWidth());
canvas.rotate(-90);
}
canvas.clipRect(0, 0, getWidth(), getHeight(), Region.Op.REPLACE);
super.draw(canvas);
}
}
I'm trying to remove and add views during onLayout in a ViewGroup, but this causes some child views not to properly redraw.
Consider the following view:
public static class MyViewGroup extends ViewGroup {
View view;
int count;
boolean removeInLayout = true;
public MyViewGroup(Context context) {
super(context);
init();
}
public MyViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
view = LayoutInflater.from(getContext()).inflate(R.layout.myview, this, false);
addView(view);
setOnClickListener(new OnClickListener() {
#Override public void onClick(View v) {
count++;
requestLayout();
}
});
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (removeInLayout) {
removeViewInLayout(view);
}
invalidate();
final String text = "Count: " + count;
((TextView) view.findViewById(R.id.one)).setText(text);
((TextView) view.findViewById(R.id.two)).setText(text);
((TextView) view.findViewById(R.id.three)).setText(text);
((TextView) view.findViewById(R.id.four)).setText(text);
if (removeInLayout) {
LayoutParams lp = view.getLayoutParams();
addViewInLayout(view, 0, lp);
final int wms = MeasureSpec.makeMeasureSpec(r - l, MeasureSpec.EXACTLY);
final int hms = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
view.measure(wms, hms);
}
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
}
#Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
measureChild(view, widthMeasureSpec, heightMeasureSpec);
}
}
With the following xml layout as a child:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="84dp">
<TextView
android:id="#+id/one"
android:layout_width="100dp"
android:layout_height="84dp"
android:background="#FF00FF00"
tools:text="First View"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/one"
android:layout_toLeftOf="#+id/four"
android:layout_centerVertical="true"
android:layout_marginLeft="4dp"
android:paddingBottom="2dp"
android:orientation="vertical">
<TextView
android:id="#+id/two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:text="Second View"/>
<TextView
android:id="#+id/three"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:fontFamily="sans-light"
android:maxLines="3"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="12sp"
tools:text="Third View"/>
</LinearLayout>
<TextView
android:id="#+id/four"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="4dp"
android:layout_marginLeft="4dp"
tools:text="Fourth view"/>
</RelativeLayout>
Initially the view and its children draw just fine, and on the first click every view is redrawn as well. Any further clicks will only cause the views with id "one" and "four" to be redrawn. "two" and "three" becomes stuck.
If I remove the invalidate() from onLayout the views are never redrawn.
If I swap out the removeViewInLayout and addViewInLayout with detachViewFromParent and attachViewToParent the views are properly redrawn. If I remove the invalidate they are never redrawn.
Can anyone shed some light on what is happening? Should it not be possible to remove and re-add a view during the layout phase? And why isn't the fact that the child view is invalidated, although while detached, enough to cause a redraw?
I have uploaded a sample app to https://github.com/SimonVT/add-in-layout - click anywhere on the screen to fire the OnClickListener which increments the count variable and requests a layout.
I'm trying to get a vertical seekbar going with the emulator, but I'm
sort of stuck. I can get the seekbar to display the way I want it to,
and I can get the progress to do what I want, and I can modify the
onTouchEvent to get the thumb to go vertically instead of
horizontally. What I can't do is get the thumb to move outside of the
default 29 horizontal pixels without using setThumbOffset(). This in
itself isn't a problem. The problem is coming from the fact that I
don't understand the thumbOffset at all -- I guess. I think I could (properly) resize the
widget, which I am pretty sure I'm not doing right. Or maybe I could
just use the thumbOffset if I could figure it out. Since I can
calculate the progress correctly I thought I would just use a linear
function of progress * (getTop() - getBottom()) of the widget but that
doesn't seem to do it. But I can't figure out what the offset is
centered around.
As a somewhat aside, I am really unsure if what I am doing in
onSizeChanged() is sane or if it's going to bite me in the ass later
on.
Here's the main.xml layout:
<?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" >
<com.mobilsemantic.mobipoll.SlideBar
android:id="#+id/slide"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:max="100"
android:progress="0"
android:secondaryProgress="25" />
<Button android:id="#+id/button"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="Hello, I am a Button" />
<TextView android:id="#+id/tracking"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
And the class (ignore the debugging junk):
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.SeekBar;
public class SlideBar extends SeekBar {
private int oHeight = 320, oWidth = 29;
private int oProgress = -1, oOffset = -1;;
private float xPos = -1, yPos = -1;
private int top = -1, bottom = -1, left = -1, right = -1;
public SlideBar(Context context) {
super(context);
}
public SlideBar(Context context, AttributeSet attrs)
{
super(context, attrs);
oOffset = this.getThumbOffset();
oProgress = this.getProgress();
}
public SlideBar(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
protected synchronized void onMeasure(int widthMeasureSpec, intheightMeasureSpec)
{
int height = View.MeasureSpec.getSize(heightMeasureSpec);
oHeight = height;
this.setMeasuredDimension(oWidth, oHeight);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(h, w, oldw, oldh);
}
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
super.onLayout(changed, l, t, r, b);
left = l;
right = r;
top = t;
bottom = b;
}
protected void onDraw(Canvas c)
{
c.rotate(90);
c.translate(0,-29);
super.onDraw(c);
}
public boolean onTouchEvent(MotionEvent event)
{
xPos = event.getX();
yPos = event.getY();
float progress = (yPos-this.getTop())/(this.getBottom()-this.getTop());
oOffset = this.getThumbOffset();
oProgress = this.getProgress();
Log.d("offset" + System.nanoTime(), new Integer(oOffset).toString());
Log.d("progress" + System.nanoTime(), new Integer(oProgress).toString());
float offset;
offset = progress * (this.getBottom()-this.getTop());
this.setThumbOffset((int)offset);
Log.d("offset_postsetprogress" + System.nanoTime(), new Integer(oOffset).toString());
Log.d("progress_postsetprogress" + System.nanoTime(), new Integer(oProgress).toString());
this.setProgress((int)(100*event.getY()/this.getBottom()));
return true;
}
}
I've created a solution which works (at least for me, anyway) and creates a vertical SeekBar.
http://hackskrieg.wordpress.com/2012/04/20/working-vertical-seekbar-for-android/
This code will correctly select/deselect the thumb, move correctly, update the listener correctly (only when the progress changes!), update/draw the progress correctly, etc. I hope it helps you.
public class VerticalSeekBar extends SeekBar {
public VerticalSeekBar(Context context) {
super(context);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas c) {
c.rotate(-90);
c.translate(-getHeight(), 0);
super.onDraw(c);
}
private OnSeekBarChangeListener onChangeListener;
#Override
public void setOnSeekBarChangeListener(OnSeekBarChangeListener onChangeListener){
this.onChangeListener = onChangeListener;
}
private int lastProgress = 0;
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
onChangeListener.onStartTrackingTouch(this);
setPressed(true);
setSelected(true);
break;
case MotionEvent.ACTION_MOVE:
// Calling the super seems to help fix drawing problems
super.onTouchEvent(event);
int progress = getMax() - (int) (getMax() * event.getY() / getHeight());
// Ensure progress stays within boundaries of the seekbar
if(progress < 0) {progress = 0;}
if(progress > getMax()) {progress = getMax();}
// Draw progress
setProgress(progress);
// Only enact listener if the progress has actually changed
// Otherwise the listener gets called ~5 times per change
if(progress != lastProgress) {
lastProgress = progress;
onChangeListener.onProgressChanged(this, progress, true);
}
onSizeChanged(getWidth(), getHeight() , 0, 0);
onChangeListener.onProgressChanged(this, getMax() - (int) (getMax() * event.getY() / getHeight()), true);
setPressed(true);
setSelected(true);
break;
case MotionEvent.ACTION_UP:
onChangeListener.onStopTrackingTouch(this);
setPressed(false);
setSelected(false);
break;
case MotionEvent.ACTION_CANCEL:
super.onTouchEvent(event);
setPressed(false);
setSelected(false);
break;
}
return true;
}
public synchronized void setProgressAndThumb(int progress) {
setProgress(getMax() - (getMax()- progress));
onSizeChanged(getWidth(), getHeight() , 0, 0);
}
public synchronized void setMaximum(int maximum) {
setMax(maximum);
}
public synchronized int getMaximum() {
return getMax();
}
}
I just placed this vertical SeekBar inside a LinearLayout with layout_height set to FILL_PARENT and layout_width set to WRAP_CONTENT.
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.safetyculture.jsadroidtablet.VerticalSeekBar
android:id="#+id/calculatorVerticalSeekBar"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="bottom"
android:max="4"
android:progress="2" />
</LinearLayout>
NOTE: You must set an OnSeekBarChangeListener, otherwise interacting with the SeekBar will produce NullPointerException.
you can download at http://560b.sakura.ne.jp/android/VerticalSlidebarExample.zip, i hope this may can help you
For API 11 and later, can use seekbar's XML attributes(android:rotation="270") for vertical effect.
<SeekBar
android:id="#+id/seekBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:rotation="270"/>
For older API level (ex API10),use: https://github.com/AndroSelva/Vertical-SeekBar-Android or see this sample here
You also have to update it's height & width as suggest by Iftikhar
In order
seekBar.setLayoutParams(
new ViewGroup.LayoutParams(convertDpToPixels(1.0f,mContext), ViewGroup.LayoutParams.WRAP_CONTENT));
//haven't tested..
where
public static int convertDpToPixels(float dp, Context context){
Resources resources = context.getResources();
return (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp,
resources.getDisplayMetrics()
);
}
Take a look at android source . I think you need to change at least trackTouchEvent and there maybe a few other places where you also need to swap the x,y coordinates to take into account your rotation of the control.
Could you leave the seekbar as horizontal, put it in a frame layout, then rotate the layout 90 degrees in the java? sounds doable...