I have an EditText, which generally shows parallel to the screen X-axis. I want to show it obliquely (around 45 degree to horizontal axis). Is it possible to do this in Android. Please guide me in a direction so that I can try for it.
After getting the two links in the answer by pawelzeiba, I proceed a little bit in solving this, but stuck again so I put another question on this. here is the link.
As Gunnar Karisson said, there is a setRotation() method in View class introduced in Android 3.0, but I cannot use it as my application should work fro Android 2.1 version.
So please help me to solve this.
EditText is an indirect subclass of View which has a rotation field you can set with setRotation(float):
myEditText.setRotation(45.0f).
After a long R & D, I succeed to solve this by creating my own custom edittext, which works perfectly as per my requirement.
public class CustomEditText extends EditText {
private Animation rotateAnim;
public CustomEditText(Context context) {
super(context);
}
public CustomEditText(Context context, AttributeSet attrs){
super(context, attrs);
}
private void createAnim(Canvas canvas) {
rotateAnim = new RotateAnimation(0, -45, 250, 50);
rotateAnim.setRepeatCount(Animation.INFINITE);
startAnimation(rotateAnim);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// creates the animation the first time
if (rotateAnim == null) {
createAnim(canvas);
}
}
}
You can rotate view, examples:
Vertical (rotated) label in Android
Is it possible to write vertically in a textview in android?
But I'm not sure how it will look with EditText during edition.
If the setRotation() method isn't available to the API level you are working with, then your best bet would be to create your own subclass of View and implement a setRotation() method.
Related
I just get going on drawing, canvas, basic animations but have stumbled upon this annoying issue:
I have a CustomView
public class CustomView extends View{
//
//Edited code ****************************
bool dir; // true -- right-to-left, false -- left-to-right
public void setDirection(bool b)
this.bool = b
// ****************************************
public CustomView(Context context) {
super(context);
...
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs)
...
}
...
//stuff for animation
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
...
}
...
and inside I have created a little animation, basically something flying from right to left over and over again.
Now, let's say I wanted to have 2 of these views in my layout. But on the second one, stuff should fly from left to right.
Is it possible to somehow pass this "parameter" to the Custom view? or do I really have to create the exact same class and change a plus sign to a minus sign and make it thereby a new class. This would mean animations created by extending view are not tunable at all.
If the latter is the case, then is there a better way to have tunable animations?
Is it possible to somehow pass this "parameter" to the Custom view?
Step #1: Add a field to your custom view to hold your animation
Step #2: Add a setter method to populate the field
Step #3: Call that setter method from something (activity, fragment, etc.) to tell it what animation to use
How do you make a horizontally scrolling ListView for vertical Mongolian script in Android apps?
Background
Android has fairly good support for many of the world's languages, even RTL languages like Arabic and Hebrew. However, there is no built in support for top-to-bottom languages like traditional Mongolian (which is still very much alive in Inner Mongolia and not to be confused with Cyrillic Mongolian). The following graphic shows the text direction with English added for clarity.
Since this functionality is not built into Android, it makes almost every single aspect of app development extremely difficult. This is expecially true with horizontal ListViews, which are not supported out of the box in Android. There is also very, very little information available online. There are a number of app developers for traditional Mongolian, but whether it is for commercial reasons or otherwise, they do not seem to make their code open source.
Because of these difficulties I would like to make a series of StackOverflow questions that can serve as a central place to collect answers for some of the more difficult programming problems related to traditional Mongolian app development. Even if you are not literate in Mongolian, your help reviewing the code, making comments and questions, giving answers or even up-voting the question would be appreciated.
Mongolian Horizontally Scrolling ListView with Vertical Script
A Mongolian ListView needs to have the following requirements:
Scrolls horizontally from left to right
Touch events work the same as with a normal ListView
Custom layouts are supported the same as in a normal ListView
Also needs to support everything that a Mongolian TextView would support:
Supports a traditional Mongolian font
Displays text vertically from top to bottom
Line wrapping goes from left to right.
Line breaks occur at a space (same as English)
The image below shows the basic functionality a Mongolian ListView should have:
My answer is below, but I welcome other ways of solving this problem.
Other related questions in this series:
How to make a traditional Mongolian script TextView in Android
How to make a traditional Mongolian script EditText in Android
More to come... (Toast, Dialog, Menu)
iOS:
How do you make a vertical text UILabel and UITextView for iOS in Swift?
Update
RecyclerViews have a horizontal layout. So it is relatively easy to put a Vertical Mongolian TextView inside one of these. Here is an example from mongol-library.
See this answer for a general solution to using a RecyclerView to make a horizontally scrolling list.
Old answer
It is quite unfortunate that horizontal ListViews are not provided by the Android API. There are a number of StackOverflow Q&As that talk about how to do them, though. Here are a couple samples:
How can I make a horizontal ListView in Android?
Horizontal ListView in Android?
But when I actually tried to implement these suggestions as well as incorporate Mongolian vertical text, I was having a terrible time. Somewhere in my search I found a slightly different answer. It was a class that rotated an entire layout. It did so by extending ViewGroup. In this way anything (including a ListView) can be put in the ViewGroup and it gets rotated. All the touch events work, too.
As I explained in my answer about Mongolian TextViews, it is not enough to simply rotate Mongolian text. That would be enough if every ListView item (or other text element in the ViewGroup) was only a single line, but rotating multiple lines make the line wrap go the wrong direction. However, mirroring the layout horizontally and also using a vertically mirrored font can overcome this, as is shown in the following image.
I adapted the rotated ViewGroup code to also do the horizontal mirroring.
public class MongolViewGroup extends ViewGroup {
private int angle = 90;
private final Matrix rotateMatrix = new Matrix();
private final Rect viewRectRotated = new Rect();
private final RectF tempRectF1 = new RectF();
private final RectF tempRectF2 = new RectF();
private final float[] viewTouchPoint = new float[2];
private final float[] childTouchPoint = new float[2];
private boolean angleChanged = true;
public MongolViewGroup(Context context) {
this(context, null);
}
public MongolViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
}
public View getView() {
return getChildAt(0);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final View view = getView();
if (view != null) {
measureChild(view, heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(resolveSize(view.getMeasuredHeight(), widthMeasureSpec),
resolveSize(view.getMeasuredWidth(), heightMeasureSpec));
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if (angleChanged) {
final RectF layoutRect = tempRectF1;
final RectF layoutRectRotated = tempRectF2;
layoutRect.set(0, 0, right - left, bottom - top);
rotateMatrix.setRotate(angle, layoutRect.centerX(), layoutRect.centerY());
rotateMatrix.postScale(-1, 1);
rotateMatrix.mapRect(layoutRectRotated, layoutRect);
layoutRectRotated.round(viewRectRotated);
angleChanged = false;
}
final View view = getView();
if (view != null) {
view.layout(viewRectRotated.left, viewRectRotated.top, viewRectRotated.right,
viewRectRotated.bottom);
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
canvas.save();
canvas.rotate(-angle, getWidth() / 2f, getHeight() / 2f);
canvas.scale(-1, 1);
super.dispatchDraw(canvas);
canvas.restore();
}
#Override
public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
invalidate();
return super.invalidateChildInParent(location, dirty);
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
viewTouchPoint[0] = event.getX();
viewTouchPoint[1] = event.getY();
rotateMatrix.mapPoints(childTouchPoint, viewTouchPoint);
event.setLocation(childTouchPoint[0], childTouchPoint[1]);
boolean result = super.dispatchTouchEvent(event);
event.setLocation(viewTouchPoint[0], viewTouchPoint[1]);
return result;
}
}
The Mongolian vertically mirrored font still needs to be set somewhere else, though. I find it easiest to make a custom TextView to do it:
public class MongolNonRotatedTextView extends TextView {
// This class does not rotate the textview. It only displays the Mongol font.
// For use with MongolLayout, which does all the rotation and mirroring.
// Constructors
public MongolNonRotatedTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public MongolNonRotatedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MongolNonRotatedTextView(Context context) {
super(context);
init();
}
// This class requires the mirrored Mongolian font to be in the assets/fonts folder
private void init() {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(),
"fonts/MongolMirroredFont.ttf");
setTypeface(tf);
}
}
Then the custom ListView item xml layout can look something like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rlListItem"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.MongolNonRotatedTextView
android:id="#+id/tvListViewText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"/>
</RelativeLayout>
Known issues:
If you look carefully at the image below you can see faint horizontal and vertical lines around the text. Although this image comes from another developer's app, I am getting the same artifacts in my app when I use the rotated ViewGroup (but not when I use the rotated TextView). If anyone knows where these are coming from, please leave me a comment!
This solution does not deal with rendering the Unicode text. Either you need to use non-Unicode text (discouraged) or you need to include a rendering engine in your app. (Android does not support OpenType smartfont rendering at this time. Hopefully this will change in the future. iOS, by comparison does support complex text rendering fonts.) See this link for a Unicode Mongolian rendering engine example.
I'm interested in using a custom View to draw, measure, and display a set of buttons that is dependent on a back-end for my application. This requires me to implement this in Android dynamically. Would you help me get started?
Here we go: first in my MainActivity I instantiate my custom class which inherits from TableLayout which is also a view:
var keyboardView = new KeyboardView(this, layout, droidLayout, this.Colors);
Then I set the content view to the fresh instance of my custom class: SetContentView(keyboardView); Here's my class's constructor which just helps me get scope on all of the info I need:
public KeyboardView(Context context, KeyboardLayout layout, int droidLayout, Dictionary<string, int> colors)
: base(context) {
this._Colors = colors;
this._Context = context;
this.KeyboardLayout = layout;
this.SetWillNotDraw(false);
//this.ButtonLayout = ll;
this.DrawingCacheEnabled = true;
this.DroidLayout = droidLayout;
I've also overridden both OnMeasure and OnDraw:
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int h = 100;
int w = 100;
//Overall keyboard/View dimensions //Difference between Canvas size and KeyboardDimensions?
this.SetMeasuredDimension(w, h);
//this.Layout.CanvasSize.
}
protected override void OnDraw(Canvas canvas) {
var bt = new Button(this._Context);
bt.Text = "laaaa";
this.AddView(bt);
}
Now what's happening is that OnDraw and OnMeasure both get it, in fact, OnDraw seems to be getting hit lots of time -- more so then I wish to count. However, the one button that I added via AddView is NOT drawn on the screen. If you guys could help me get this one button on the screen I can get to writing the core logic!
On a side-note: I can draw stuff on my screen if I set an XML layout file as the view as such: SetContentView(Resource.Layout.LayoutName) But, since the nature of my program requires dynamic views being added all the time, I'd rather avoid writing lengthy Layout files. Thanks guys! Bump my question up if you think it's a worthwhile one!
In general, this is a good place to start. In particular it details how to add custom attributes, how to perform custom drawing, and how to design custom events that make sense in the context of your own application.
Also, it looks like you're trying to use C# style syntax in Java, which won't work for things like inheritance. Reading some java tutorials might help you out.
This is a good resource for that and should help you get up and going. Good luck!
Don't forget to call the super() to allow the parent class to do what it needs to do for the overridden method.
protected override void OnDraw(Canvas canvas) {
super(canvas)
}
Related link
http://developer.android.com/guide/topics/ui/custom-components.html#compound
I'm not sure if this is possible, and I couldn't find a topic based on it, but if it's been answered before drop me a link and that will be that.
What I'm looking to do right now is resize some of the default Android widgets, specifically DatePicker and TimePicker, to use in an Activity. But as far as I can see the only result of modifying the width or height of either Picker (in a negative direction) results in a cropped view, rather than a scaled/stretched view of the widget.
I am open to my own custom widgets of my own, but I would really prefer to keep this project as simple and clean as possible, matching the Android OS UI as much as possible, so using the native DatePicker and TimePicker seems like a logical choice to me. If anyone knows how to scale these widgets down rather than cropping them, I'd really appreciate it.
Thanks.
It is a very bad hack, but it should work:
Create a new view extending LinearLayout, overwrite method getChildStaticTransformation and setStaticTransformationsEnabled explicit to true.
In the method getChildStaticTransformation you can manipulate the tranformation parameter to scale down all the content of your extended LinearLayout.
And then add the DatePicker or something else as a child of this view.
EG:
public class ZoomView
extends LinearLayout
{
private float sf = 1f;
public ZoomView(final Context context, final AttributeSet attrs)
{
super(context, attrs);
setStaticTransformationsEnabled(true);
}
public ZoomView(final Context context)
{
super(context);
setStaticTransformationsEnabled(true);
}
public void setScaling(final float sf)
{
this.sf = sf;
}
#Override
protected boolean getChildStaticTransformation(final View child, final Transformation t)
{
t.clear();
t.setTransformationType(Transformation.TYPE_MATRIX);
final Matrix m = t.getMatrix();
m.setScale(this.sf, this.sf);
return true;
}
}
I am trying to create a "hidden edit view" which will give me the functionality of text editing within a 3rd party GUI on Android. I figured that the easiest way to make it not draw would be to just override onDraw() with a no-op; however it's having no effect. I've added a log statement to check that it is being called. Does anyone have an idea why it's still being drawn?
private class HiddenEditText extends EditText
{
public HiddenEditText(Context context)
{
super(context);
}
#Override
protected void onDraw(Canvas canvas)
{
Log.e("DBG", "onDraw()");
}
}
// ...
EditText EditTextGreen = new HiddenEditText(this);
EditTextGreen.setFocusable(true);
EditTextGreen.setLayoutParams(new TableLayout.LayoutParams(TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
layout.addView(EditTextGreen, 0);
Another way of achieving this result, is to specify the background of the EditText as transparent:
<EditText android:background="#android:color/transparent" ...
The background is drawn by View.draw(). onDraw() is invoked by View.draw(), so you need to follow Mannaz' advice and set the background to a transparent color or just set it to null.