everyone. I'm sort of new to android development and I've ran into a bit of a problem.
As is it's written in the title, I'm trying to create an app in which a button moves to a random location on the screen every time it is clicked. A sort of a "runaway button" thingy.
Here is the XML code.
<?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:id="#+id/activity_main"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:background="#color/colorPrimary"
tools:context="com.example.a4ld.MainActivity">
<Button
android:id="#+id/button01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/button" />
</LinearLayout>
And here is the main activity code.
At first the solution seems pretty simple. Just move the random values into the onClick method. That way new coordinates would get generated every time the button is clicked. But whenever I do that the animationListener class cannot reach those values and move the view accordingly so that the clickable area of the button would match its position on the screen.
package com.example.a4ld;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.LinearLayout;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//get display size.
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
final int height = displayMetrics.heightPixels;
final int width = displayMetrics.widthPixels;
//generates random values within display size range.
//doesn't work as intended. the button still goes out of bounds sometimes.
Random n = new Random();
final int height01 = n.nextInt(height - 0) + 0;
Random m = new Random();
final int width01 = m.nextInt(width - 0) + 0;
final Button button01 = (Button) findViewById(R.id.button01);
button01.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//animates button movement.
TranslateAnimation animation01 = new TranslateAnimation(0, width01, 0, height01);
animation01.setDuration(500);
animation01.setAnimationListener(new animationListener());
button01.startAnimation(animation01);
}
class animationListener implements Animation.AnimationListener {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
//moves the view(probably) to match the new button position.
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(button01.getWidth(), button01.getHeight());
layoutParams.setMargins(width01, height01, 0, 0);
button01.setLayoutParams(layoutParams);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
}
});
}
}
Pardon me for any mistakes. This is my first time asking for help here.
Every bit of help will be greatly appreciated and thank you for your time.
You should rather use ViewPropertyAnimator. This animates the view to its future position and you don't need to force any layout params on the view after the animation ends. And it's rather simple.
myView.animate().x(50f).y(100f);
myView.animate().translateX(pixelInScreen)
Note: This pixel is not relative to the view. This pixel is the pixel position in the screen.
Related
I am putting a bunch of buttons in LinearLayout, with weight=1 for each. The problem is, that when the setTextSize gets called, it sometimes changes the space the background is drawn on (so if the new text size is smaller the one button has perceived height FE 2/3 of all the other buttons). The onSizeChanged gets never called even though the size drawn changes. The button does not change it's postion (debug by getLocationInWindow) neither it's size (getWidth, getHeight).
Am I doing something wrong, or is there at least a way to fix it?
MainActivity:
import android.app.ActionBar;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewGroup mainLayout = (ViewGroup)findViewById(R.id.mainLayout);
LinearLayout l = new LinearLayout(this);
mainLayout.addView(l);
for (int i = 0; i < 8; i++) {
Button b = new Button(this);
LinearLayout.LayoutParams p1 = new LinearLayout.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT, 200);
p1.weight = 1;
b.setLayoutParams(p1);
b.setBackgroundColor(Color.YELLOW);
l.addView(b);
}
Button b = ((Button)l.getChildAt(7));
b.setTextSize(50f);
}
}
And for it to be all, XML:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:id="#+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="dracek.fit.cvut.cz.test.MainActivity">
</android.support.constraint.ConstraintLayout>
I tried all this for the button but no change:
requestLayout();
invalidate();
ViewParent vp = getParent();
if (vp != null)
vp.requestLayout();
So I will answer myself if noone else does so.
In the end I found out, that the LinearLayout is for whatever reason trying to have all the text baselines in the same height, thus moving the buttons. Adding one line solves the problem:
p1.gravity =Gravity.FILL;
This question already has an answer here:
image is playing an animation and the image is clickable
(1 answer)
Closed 10 years ago.
I've made a simple animation for an image and I set the event OnClick on the image to make a toast. The problem is that I made the image started doing the animation on the onCreate and I made set the image to be clicked and fire the toast but the problem is that the image isn't clickable, but if I press on the original position of the image, the toast is started (the image is not moving with the animation)
thx for your help
this is the animation code in anim folder (translate.xml)
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator">
<translate
android:fromXDelta="-80%p"
android:toXDelta="80%p"
android:duration="20000"
android:repeatCount="100"
android:repeatMode="restart"
/>
</set>
and this is the Activity Class
package com.example.animatest;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
private ImageView image01;
private long aefe;
private ImageView image1;
private ImageView image2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image01 = (ImageView) findViewById(R.id.imageView1);
final Animation animTranslate1 = AnimationUtils.loadAnimation(this,
R.anim.translate);
image01.startAnimation(animTranslate1);
image01.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "hello", Toast.LENGTH_SHORT)
.show();
}
});
}
}
During the entire animation, your view remains at the old location (location when the animation just started). It is just drawn in another spot. You'd have to move your animated view after your animation ends:
Register a listener to your animation.
http://developer.android.com/reference/android/view/animation/Animation.AnimationListener.html
In your onAnimationEnd implementation, modify your Activity's layout so that it resembles the final state/layout of your animation.
Update after your comment:
The only way I see of doing this is by creating your own custom Animation in Java code and implementing your custom Animation's 'protected void applyTransformation(float interpolatedTime, Transformation t)' method. For example, in our app we have an animation that actually moves a View around instead of just drawing it at a different location. E.g. below is an example of an Animation that increases or decreases the actual height of a View:
public class ViewHeightAnimation extends Animation {
private final View view;
private final float diffHeight;
private final int startHeight;
public ViewHeightAnimation(View view, float diffHeight, int startHeight) {
this.view = view;
this.diffHeight = diffHeight;
this.startHeight = startHeight;
setDuration(200);
setInterpolator(new AccelerateDecelerateInterpolator());
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
android.view.ViewGroup.MarginLayoutParams layoutParams = (android.view.ViewGroup.MarginLayoutParams)view.getLayoutParams();
layoutParams.height = Math.round(startHeight + (diffHeight * interpolatedTime));
view.setLayoutParams(layoutParams);
}
#Override
public boolean willChangeBounds() {
return true;
}
}
Your Animation would be different, but would be using the 'getLayoutParams()' and 'setLayoutParams()' as well to modify the View's (ImageView's) position and change layoutParams.topMargin and layoutParams.leftMargin appropriately.
If you are not concerned about Android 2.x or lower, using the ObjectAnimator (3.0 or higher) or ViewPropertyAnimator (3.1 or higher) is a better solution, as was mentioned in other answer earlier.
Let me know if this helps you.
try like this:
final Animation animTranslate1 = AnimationUtils.loadAnimation(this,R.anim.translate);
animTranslate1.setFillAfter(true);
image01.startAnimation(animTranslate1);
If that does not work then you'll have to use the newer Property Animation framework (which was pointed out in the answer to your previous duplicate question)
See here to learn about it
The way you animate your imageView is only move its appearance, so actually your imageView is still at the old position. There's not an easy way to do what you want, with this type animations. You should consider to use ObjectAnimators ...
I am animating three views that are stacked on top of each other. When I tap one that is not the front view, one or two views will slide up or down to uncover the tapped view, bring the tapped view to front, and then return everything to their original position. Most of these work fine. Only when I bring a view to front that I just animated away I get a noticeable flicker.
I have read at least a hundred posts but none contains the solution.
I am posting this to consolidate every suggested solution in one place and to hopefully find a solution.
I know that the animation does not animate the view itself, but just an image. The view stays at its original position. It is definitely related to that. It only happens when bringing a view to front that just moved.
Moving the view to the animation end position before starting the animation or after the animation is finished does not help one bit.
It also is not related to the AnimationListener.onAnimationEnd bug, since I derived my own views and intercept onAnimationEnd there.
I am using Animation.setFillAfter and Animation.setFillEnabled to keep the final image at the animation end location.
I tried using Animation.setZAdjustment but that one only works for entire screens, not views within a screen.
From what I have learned I suspect that the problem is bringToFront() itself, which does a removeChild()/addChild() on the parent view. Maybe the removeChild causes the redraw showing the view without the removed child briefly.
So my questions: Does anyone see anything I missed that could fix this?
Does Android maybe have a command to temporarily stop drawing and resume drawing later. Something like a setUpdateScreen(false) / setUpdateScreen(true) pair?
That would allow me to skip the flicker stage.
Minimal code to demo the effect follows. Tap white to see red move up and back down behind white without flicker (white comes to front but does not move). Then tap red to see red move back up from behind white and the flicker when it is brought to front just before it slides back down over white. Weird thing is that the same thing does not always happen when using blue instead of red.
MainActivity.java
package com.example.testapp;
import com.example.testapp.ImagePanel.AnimationEndListener;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.TranslateAnimation;
public class MainActivity extends Activity
{
private static final int ANIMATION_TIME = 1000;
private ImagePanel mRed;
private ImagePanel mWhite;
private ImagePanel mBlue;
private int mFrontPanelId;
private void animate(final ImagePanel panel, final int yFrom, final int yTo,
final AnimationEndListener animationListener)
{
final TranslateAnimation anim = new TranslateAnimation(0, 0, 0, 0, 0, yFrom, 0, yTo);
anim.setDuration(ANIMATION_TIME);
anim.setFillAfter(true);
anim.setFillEnabled(true);
if (animationListener != null)
{
panel.setAnimListener(animationListener);
}
panel.startAnimation(anim);
}
public void onClick(final View v)
{
final int panelId = v.getId();
if (mFrontPanelId == panelId)
{
return;
}
final ImagePanel panel = (ImagePanel) v;
final int yTop = mWhite.getTop() - mRed.getBottom();
final int yBot = mWhite.getBottom() - mBlue.getTop();
final boolean moveRed = panelId == R.id.red || mFrontPanelId == R.id.red;
final boolean moveBlue = panelId == R.id.blue || mFrontPanelId == R.id.blue;
animate(mBlue, 0, moveBlue ? yBot : 0, null);
animate(mRed, 0, moveRed ? yTop : 0, new AnimationEndListener()
{
public void onBegin()
{
}
public void onEnd()
{
// make sure middle panel always stays visible
if (moveRed && moveBlue)
{
mWhite.bringToFront();
}
panel.bringToFront();
animate(mBlue, moveBlue ? yBot : 0, 0, null);
animate(mRed, moveRed ? yTop : 0, 0, new AnimationEndListener()
{
public void onBegin()
{
}
public void onEnd()
{
}
});
mFrontPanelId = panelId;
}
});
}
#Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRed = (ImagePanel) findViewById(R.id.red);
mWhite = (ImagePanel) findViewById(R.id.white);
mBlue = (ImagePanel) findViewById(R.id.blue);
mFrontPanelId = R.id.red;
}
}
ImagePanel.java
package com.example.testapp;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
public class ImagePanel extends ImageView
{
public interface AnimationEndListener
{
public void onBegin();
public void onEnd();
}
private AnimationEndListener mAnim = null;
public ImagePanel(final Context context)
{
super(context);
}
public ImagePanel(final Context context, final AttributeSet attrs)
{
super(context, attrs);
}
public ImagePanel(final Context context, final AttributeSet attrs, final int defStyle)
{
super(context, attrs, defStyle);
}
#Override
protected void onAnimationEnd()
{
super.onAnimationEnd();
clearAnimation();
if (mAnim != null)
{
final AnimationEndListener anim = mAnim;
mAnim = null;
anim.onEnd();
}
}
#Override
protected void onAnimationStart()
{
super.onAnimationStart();
if (mAnim != null)
{
mAnim.onBegin();
}
}
public void setAnimListener(final AnimationEndListener anim)
{
mAnim = anim;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.example.testapp.ImagePanel
android:id="#+id/blue"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="#000080"
android:src="#drawable/testpattern"
android:onClick="onClick" />
<com.example.testapp.ImagePanel
android:id="#+id/white"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#808080"
android:src="#drawable/testpattern"
android:onClick="onClick" />
<com.example.testapp.ImagePanel
android:id="#+id/red"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:adjustViewBounds="true"
android:background="#800000"
android:src="#drawable/testpattern"
android:onClick="onClick" />
</RelativeLayout>
testpattern.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<gradient
android:startColor="#00000000"
android:endColor="#ffffffff" />
</shape>
Do you need all the images be visible at any time? you can set their visibility as invisible so they will not disturb you. you make them visible again once you need them.
Try calling animation.cancel() in onAnimationEnd. I remember a while back I had a similar issue with animation flickering after executing code in onAnimationEndand that did the trick.
I was observing the same problems when calling bringToFront() during an animation.
I could solve my problem by using setChildrenDrawingOrderEnabled(boolean enabled) and getChildDrawingOrder(int childCount, int i) on the ViewGroup that contained the children I was animating.
I have not found a solution for my problem, maybe you can help me here.
I am using a RelativeLayout with an ImageView and a TextView as children. The TextView contains a large text and should scroll from right to left. But everytime when I set a new image to the ImageView, the marquee starts from beginning.
I think that by setting a new image the TextView looses its focus and so the marquee starts again. How can I prevent that or is there something else I am doing wrong? Would be great if someone could point me to the correct solution.
Thanks a lot!
You can reproduce my problem with this code:
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils.TruncateAt;
import android.view.Display;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class RelativeLayoutActivity extends Activity {
private ImageView mImageView;
private TextView mTextView;
private Handler mHandler = new Handler();
private int mCurrentImage = 0;
private Runnable mCallback = new Runnable() {
#Override
public void run() {
toggleImage();
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initLayout();
setLongText();
mHandler.postDelayed(mCallback, 5000);
}
private void initLayout() {
RelativeLayout layout = (RelativeLayout) findViewById(R.id.parentLayout);
Display display = getWindowManager().getDefaultDisplay();
int screenWidth = display.getWidth();
int screenHeight = display.getHeight();
mImageView = new ImageView(this);
mImageView.setScaleType(ScaleType.FIT_XY);
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(screenWidth,screenHeight);
mImageView.setImageDrawable(this.getResources().getDrawable(R.drawable.red));
layout.addView(mImageView, rlp);
// marquee text at the bottom
mTextView = new TextView(this);
mTextView.setSingleLine();
mTextView.setEllipsize(TruncateAt.MARQUEE);
mTextView.setMarqueeRepeatLimit(-1);
mTextView.setHorizontallyScrolling(true);
mTextView.setFocusable(true);
mTextView.setFocusableInTouchMode(true);
mTextView.setBackgroundColor(Color.BLACK);
mTextView.setTextColor(Color.WHITE);
rlp = new RelativeLayout.LayoutParams(screenWidth, 50);
rlp.topMargin = screenHeight-100;
layout.addView(mTextView, rlp);
}
private void setLongText() {
StringBuilder sb = new StringBuilder();
for (int i=0; i<50; i++) {
sb.append(" ");
}
for (int i=0; i<50; i++) {
sb.append("A");
}
for (int i=0; i<50; i++) {
sb.append("B");
}
for (int i=0; i<50; i++) {
sb.append("C");
}
mTextView.setText(sb.toString());
mTextView.setSelected(true);
}
private void toggleImage() {
mCurrentImage++;
if (mCurrentImage % 2 == 0) {
mImageView.setImageDrawable(this.getResources().getDrawable(R.drawable.red));
} else {
mImageView.setImageDrawable(this.getResources().getDrawable(R.drawable.green));
}
mHandler.postDelayed(mCallback, 5000);
}
}
I had a same problem and I fixed it just now:)
If your TextView which in layout XML contains layout_weight
android:layout_weight="1"
Remove it!This attibute cause marquee restart.
Hope helpful:)
The marquee reset problem is because of loss of focus of the TextView on which it is running. To overcome these issues you can simply surround your TextView with another RelativeLayout so that it is in a different ViewGroup as your other views.
You have another option: Create a new class that is a subclass of TextView and override onFocusChanged and onWindowFocusChanged to prevent loss of focus for the said textview.
That's it. Using these techniques your marquee won't restart every time another element gains focus.
See my answer here : https://stackoverflow.com/a/13841982/1823503
The idea is :
to fix the width and height programmatically (you did it)
to setSelected (you did it)
to Override your TextView to fix the focus problems
just a simple Fix..:) no need to worry much...just fix width of textview as some 800dp or too higher width. it will solve reset issue
<TextView
android:id="#+id/adv_txt_view"
android:layout_width="800dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:singleLine="true"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:marqueeRepeatLimit="marquee_forever"
android:focusableInTouchMode="true"
android:focusable="true"
android:scrollHorizontally="true"
android:textColor="#color/black"
android:text="large text to scroll!!" />
I am trying to make a view controller that is fixed in portrait mode, but that has a landscape version that can "fade in" over the top. What this means is that I need to be able to have a version of the screen that is the correct size for landscape, and is rotated 90 (or 270 depending) degrees. On iPhone this was easy, but I'm struggling with Android. I've got a custom view containing the view I want rotated, but I can't seem to size the child view correctly, or get the rotation to line up correctly. Is there an easier way? Alternatively, what am I doing wrong here?
#Override
protected void onDraw(Canvas canvas) {
if (getChildCount() == 1) {
canvas.save();
canvas.rotate(90, canvas.getWidth() / 2, canvas.getHeight() / 2);
// I have no idea what my pivot point should be
View child = getChildAt(0);
Bitmap bitmap = // bitmap of child
Paint paint = new Paint();
canvas.drawBitmap(bitmap, 0, 0, paint);
canvas.restore();
}
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if (getChildCount() == 1) {
View child = getChildAt(0);
child.layout(top, left, bottom, right);
}
}
What is not helpful is suggesting actually changing the orientation of the view controller. I need it to stay in portrait mode in order to show the portrait version at the same time with a partial alpha transparency.
To be clear, I need to be able to interact with the view in its rotated coordinates, so I need to be able to press buttons, use a scrollview, etc.
API Level 11 introduces setRotationX/Y for Views, which seems to be exactly what you're looking for.
Supposing Honeycomb is not you target API version, here's what I found out after a few hours toying with this (definitely more challenging than my current project!):
Rendering is certainly doable (and relatively easy)
It's a massive hack and you shouldn't be doing it in the first place
Basically, the main issue is not rendering but processing events. Since Android has no idea that the view is sideways (you just rendered it that way), the view will respond to the area bounded by original pre-rotation coordinates. Therefore, no clicking (well, unless you have a square button that just has the text sideways!).
Really, you should probably look into backporting the Honeycomb changes.
With that said and with a large disclaimer that there might be a multitude of cases where this won't work, here's a sample app:
package com.side;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
public class TestActivity extends Activity {
private class SidewaysGroup extends ViewGroup{
public SidewaysGroup(Context context) {
super(context);
}
#Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
Log.i("Sideways", "Parent size: " + getWidth() + "x" + getHeight() + ", child size: " + child.getWidth() + "x" + child.getHeight());
// Create a new canvas for the child (there's probably a way to use the original canvas but I couldn't figure out the transformations)
Canvas childCanvas = new Canvas();
Bitmap childBitmap = Bitmap.createBitmap(child.getWidth(), child.getHeight(), Bitmap.Config.ARGB_8888);
childCanvas.setBitmap(childBitmap);
boolean ret = super.drawChild(childCanvas, child, drawingTime);
Matrix matrix = new Matrix();
// rotate at the bottom left corner
matrix.postRotate(90f, 0, childBitmap.getHeight());
// after the rotation we are one `height` further down than we should be
matrix.postTranslate(0, -childBitmap.getHeight());
canvas.drawBitmap(childBitmap, matrix, new Paint());
return ret;
}
#Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
if(changed && getChildCount()==1)
{
final View child = getChildAt(0);
// This is breaking the flow (measuring would be done twice) - should be moved to onMeasure or measure() itself
// notice that it inverts the dimensions
child.measure(MeasureSpec.makeMeasureSpec(getMeasuredHeight(),
MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(
getMeasuredWidth(), MeasureSpec.AT_MOST));
child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
}
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView verticalView = new TextView(this);
verticalView.setText("This is the vertical text");
verticalView.setGravity(Gravity.CENTER);
verticalView.setTextSize(50f);
verticalView.setTextColor(Color.parseColor("#88ffffff")); // add a bit of transparency to the text
SidewaysGroup group = new SidewaysGroup(this);
Button horizontalButton= new Button(this);
horizontalButton.setText("This is the horizontal button");
horizontalButton.setGravity(Gravity.CENTER);
horizontalButton.setTextSize(50f);
horizontalButton.setBackgroundDrawable(null);
horizontalButton.setTextColor(Color.WHITE);
horizontalButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Log.i("Sideways", "Button click");
}
});
group.addView(horizontalButton);
RelativeLayout mainLayout = new RelativeLayout(this);
RelativeLayout.LayoutParams relparams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
relparams.addRule(RelativeLayout.CENTER_IN_PARENT);
mainLayout.addView(verticalView, relparams);
mainLayout.addView(group, relparams);
setContentView(mainLayout);
mainLayout.requestLayout();
}
}
Focusing and translating events are left as an exercise to the reader :)
Do You want to scroll in both views (Vertical and Horizontal?)
If not, maybe you can take a screenshot of the vertical text (see here ) then do an actual rotation of your layout (i know you didn't want that but I don't understand why, if the vertical view is just needed as an overlay) and then use the screenshot of the vertical screen as an simple transparent bitmap overlay...
From your comments it sounds like you want this:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:id="#+id/linearlayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" />
</LinearLayout>
<LinearLayout
android:id="#+id/linearlayout2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />
</LinearLayout>
</FrameLayout>
but I can't see how or why you would want this