I am coding an Android game in which 2 players play at the same time. One player faces the phone in a normal way and the other faces it upside down.
As it is a quiz, I didn't use any canvas or graphics. It contains only 2 linear layouts and one of them is supposed to be upside down. For this I have used:
android:rotation="180"
for one of the layouts.
it showed upside down on the graphical view of my xml in Eclipse but when I run it on an emulator or a phone it is not inverted or rotated to 180 degrees.
XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" android:clipToPadding="false"
android:rotation="180">
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
</LinearLayout
Java Code
public class x extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
How can I rotate it without complication. I am presently using api level 15 but i have no restriction on API level.
I would suggest that you create a custom Layout that will handle the rotation on it's onDraw()
public class RotatedLinearLayout extends RotatedLinearLayout {
final boolean topDown;
public RotatedLinearLayout (Context context){
super(context);
}
public RotatedLinearLayout (Context context, AttributeSet attrs){
super(context, attrs);
}
public RotatedLinearLayout (Context context, AttributeSet attrs, int defStyle){
super(context, attrs,defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
#Override
protected void onDraw(Canvas canvas){
TextPaint textPaint = getPaint();
textPaint.setColor(getCurrentTextColor());
textPaint.drawableState = getDrawableState();
canvas.save();
if(topDown){
canvas.translate(getWidth(), 0);
canvas.rotate(180);
}else {
canvas.translate(0, getHeight());
canvas.rotate(-180);
}
canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
getLayout().draw(canvas);
canvas.restore();
}
}
When you write your XML, use the VerticalRelativeLayout instead of the other layout you tried to create.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<path.to.package.RotatedLinearLayout
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" android:clipToPadding="false"
>
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</path.to.package.RotatedLinearLayout >
</LinearLayout
Related
I have a layout which contains only a LinearLayour with 3 buttons inside.
I would want this 3 buttons to fill the screen vertically so I used "weigth=1" but I should also want the buttons to be square, that is, that their width is equal to their height.
Any way to do it?
Here's the .xml file
<?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:layout_width="match_parent"
android:layout_height="match_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"
tools:context="android.jose.se.Prueba"
android:background="#drawable/bg"
android:gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="#+id/bHet"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#drawable/layer1"
android:onClick="cambiarBoton"/>
<Button
android:id="#+id/bGay"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#drawable/layer2"
android:onClick="cambiarBoton"/>
<Button
android:id="#+id/bLesbi"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#drawable/layer3"
android:onClick="cambiarBoton"/>
</LinearLayout>
</RelativeLayout>
I had similar issue and done it using Google's Percent Relative Layout that helps you manage view aspect ratio.
You can use it like this
<android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="match_parent"
app:layout_aspectRatio="100%"/>
</android.support.percent.PercentFrameLayout>
The best way to do this, is to make a new Class called Square button and this class should extend Button. Then in the onMeasure of this class, simply make your heightSpec as WidthSpec.
public class SquareButton extends Button {
public SquareButton(Context context) {
super(context);
}
public SquareButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int WidthSpec, int HeightSpec){
int newWidthSpec = HeightSpec ;
super.onMeasure(newWidthSpec, HeightSpec);
}}
Now you can use this SquareButton instead of a normal Button in your xml like this. The value of android:width attribute will be ignored.
<com.example.package.SquareButton
android:height = "0dp"
android:weight = "1"
android:width = "0dp"
/>
I'm quite new to Android programming and I'm stuck on an simple problem.
I have a basic homepage with some buttons and a logo. I use a LinearLayout and the layout_weight attribute to distribute all the components.
Here is my code :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_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:orientation="vertical"
tools:context="iut.project.findmeapp.MainActivity" >
<ImageView
android:id="#+id/activityMainAppLogoIv"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:contentDescription="#string/description_logo"
android:layout_weight="1"
android:maxHeight="#dimen/img_maxHeight"
android:layout_margin="#dimen/img_margin"
android:src="#drawable/ic_launcher" />
<Button
android:id="#+id/activityMainMyEventsBtn"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:layout_marginTop="#dimen/button_margin_vertical"
android:layout_marginBottom="#dimen/button_margin_vertical"
android:layout_weight="1"
android:text="#string/my_events" />
<Button
android:id="#+id/activityMainMyContactsBtn"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:layout_marginTop="#dimen/button_margin_vertical"
android:layout_marginBottom="#dimen/button_margin_vertical"
android:layout_weight="1"
android:text="#string/my_contacts" />
<Button
android:id="#+id/activityMainLastNotifBtn"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:layout_marginTop="#dimen/button_margin_vertical"
android:layout_marginBottom="#dimen/button_margin_vertical"
android:layout_weight="1"
android:text="#string/last_notification" />
<TextView
android:id="#+id/activityMainCopyrightTv"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:gravity="center"
android:layout_weight="0.5"
android:layout_margin="#dimen/tw_margin"
android:text="#string/copyright" />
</LinearLayout>
(Note : #dimen/null_height is 0dp)
My problem is that I want the image to scale with the size of the screen, but I don't want it pixelated : I have set a maximum height of 200px.
The following lines don't seem to work, because the image has no limit and totally ignores the maxHeight attribute.
android:layout_weight="1"
android:maxHeight="#dimen/img_maxHeight"
Actually it looks like this (example image) :
It works perfectly, but when I set maxHeight to 10px for example, nothing changes.
How can I achieve this ? I highly prefer to use a LinearLayout.
Thank you in advance.
Thanks to Evripidis Drakos for pointing me in the right direction. Just need a check to only set the max height if it's actually required.
public class MaxHeightImageView extends ImageView {
public static final int MAX_HEIGHT_NOT_SET = -1;
public static final int INDEX_MAX_HEIGHT = 0;
private static final int[] STYLE_ATTRIBUTE_ARRAY = {
android.R.attr.maxHeight,
};
private int myMaxHeight;
public MaxHeightImageView(Context context) {
super(context);
init(context, null);
}
public MaxHeightImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public MaxHeightImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public MaxHeightImageView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int size = MeasureSpec.getSize(heightMeasureSpec);
if(MAX_HEIGHT_NOT_SET != myMaxHeight && size > myMaxHeight) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(myMaxHeight, MeasureSpec.AT_MOST);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private void init(Context context, AttributeSet attrs) {
if(context != null) {
TypedArray ta = context.obtainStyledAttributes(attrs,
STYLE_ATTRIBUTE_ARRAY);
myMaxHeight = ta.getDimensionPixelSize(INDEX_MAX_HEIGHT, 0);
} else {
myMaxHeight = MAX_HEIGHT_NOT_SET;
}
}
}
I dont think that you can combine layout_weight with maxHeight.
You could try subclassing ImageView to override the onMeasure method like so:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(200, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
if u want to set exact height for your image u should use weightSum property with weight
edit:
for fixed height do not give weight for imageview just take parent layout for imageview then add weight for that linear layout(parent layout) and for imageview give height as wrap content and maxHeight. when u use weight with height="0dp" the content will capture the whole height so it will ignore maxHeight.
try this
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
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:weightSum="5"
tools:context="iut.project.findmeapp.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="#+id/activityMainAppLogoIv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:contentDescription="#string/quantity_hint"
android:maxHeight="200px"
android:src="#drawable/ic_launcher" />
</LinearLayout>
<Button
android:id="#+id/activityMainMyEventsBtn"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="my_events" />
<Button
android:id="#+id/activityMainMyContactsBtn"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="my_contacts" />
<Button
android:id="#+id/activityMainLastNotifBtn"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="last_notification" />
<TextView
android:id="#+id/activityMainCopyrightTv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight=".5"
android:gravity="center"
android:text="copyright" />
</LinearLayout>
My activity is in LANDSCAPE mode
I am using following code.
Activity_main.xml
<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="match_parent">
<TextView
android:id="#+id/sample"
android:layout_height="80dp"
android:layout_width="match_parent"
android:text="saga"/>
<com.example.sample.Circle
android:id="#+id/circle"
android:background="#AD9999"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/sample"/>
</RelativeLayout>
Circle.java
public class Circle extends View{
public Circle(Context context) {
super(context);
this.context=context;
}
public Circle(Context context, AttributeSet attrs) {
super(context, attrs);
this.context=context;
mOuterDialPaint.setColor(Color.BLUE);
}
#Override
public void onDraw(Canvas canvas)
{
float width=canvas.getWidth()/2;
Log.i("Width", ""+canvas.getHeight());
float dialCenterX=width;
canvas.drawCircle(dialCenterX, canvas.getHeight(), dialCenterX, mOuterDialPaint);
}
}
So canvas is drawing circle from specified positions but not moving below textview so textview is coming on top of canvas and some part is getting cut. So any fix for this problem??
Use frame-Layout in xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.sample.Circle
android:id="#+id/circle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#AD9999" />
<TextView
android:id="#+id/sample"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="top"
android:gravity="center"
android:text="your text view" />
</FrameLayout>
I have a LinearLayout which has its margins cut off and I've tried fiddling around with the XML as well as the FlyOutContainer class in order to fix it, no luck.
I want my LinearLayout to fit on any android screen. Can anyone point me in the right direction on how to fix this problem? And can anyone explain to me why the margins are being cut off, so if this happens again I know what to do?
Here is what my LinearLayout menu looks like:
Here is the FlyOutContainer class:
public class FlyOutContainer extends LinearLayout {
private View menu; //Menu of application
private View content; //Content of application
protected static final int menuMargin = 150;
public enum MenuState {
CLOSED, OPEN
};
protected int currentContentOffset = 0;
protected MenuState menuCurrentState = MenuState.CLOSED;
public FlyOutContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public FlyOutContainer(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FlyOutContainer(Context context) {
super(context);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
this.menu = this.getChildAt(0);
this.content = this.getChildAt(1);
this.menu.setVisibility(View.GONE);
}
#Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
if (changed)
this.calculateChildDimensions();
this.menu.layout(left, top, right - menuMargin, bottom);
this.content.layout(left + this.currentContentOffset, top, right
+ this.currentContentOffset, bottom);
}
public void toggleMenu() {
switch (this.menuCurrentState) {
case CLOSED:
this.menu.setVisibility(View.VISIBLE);
this.currentContentOffset = this.getMenuWidth();
this.content.offsetLeftAndRight(currentContentOffset); this.menuCurrentState = MenuState.OPEN;
break;
case OPEN:
this.content.offsetLeftAndRight(-currentContentOffset);
this.currentContentOffset = 0;
this.menuCurrentState = MenuState.CLOSED;
this.menu.setVisibility(View.GONE);
break;
}
this.invalidate();
}
private int getMenuWidth() {
return this.menu.getLayoutParams().width;
}
private void calculateChildDimensions() {
this.content.getLayoutParams().height = this.getHeight();
this.content.getLayoutParams().width = this.getWidth();
this.menu.getLayoutParams().width = this.getWidth() - menuMargin;
this.menu.getLayoutParams().height = this.getHeight();
}
}
Here is my XML:
<FlyOutContainer.FlyOutContainer xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:facebook="http://schemas.android.com/apk/res-auto"
style="#style/Container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/menu_Child"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#000000"
android:orientation="vertical" >
<com.facebook.widget.ProfilePictureView
android:id="#+id/profilePicture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
facebook:is_cropped="true"
facebook:preset_size="small" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="toggleMenu"
android:text="#string/button_1" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="toggleMenu"
android:text="#string/button_2" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="toggleMenu"
android:text="#string/button_3" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="toggleMenu"
android:text="#string/button_4" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="toggleMenu"
android:text="#string/button_5" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="toggleMenu"
android:text="#string/button_6" />
</LinearLayout>
<!-- The navigation drawer -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#android:color/transparent"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/defined_Text" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="toggleMenu"
android:text="#string/Toggle_Menu" />
</LinearLayout>
Would appreciate any guidance.
So I fixed the problem by taking out style="#style/Container out of my XML, for some weird reason my theme which is custom made was making extra padding on all four sides of the Layout.
So in summary changing XML to this fixed it:
<FlyOutContainer.FlyOutContainer xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:facebook="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
....
....
....
</FlyOutContainer.FlyOutContainer>
IMPROVED ANSWER:
What's the point of UI design if you can't keep your background right :) ? In order to keep the style I had previously implemented I saw that in my styles.xml in res there was an extra padding of this 16 dp like so:
<style name="Container" >
<item name="android:layout_margin">0dp</item>
<item name="android:padding">16dp</item> <!-- REMOVE HERE!!! -->
<item name="android:orientation">vertical</item>
<item name="android:background">#drawable/background</item>
</style>
removing that line allowed me to keep my background
I just created a view for displaying PDF file
public class PDFGraphic extends View{
String mText;
float mLastX;
float mLastY;
public float mOffX;
public float mOffY;
Canvas mCan;
Bitmap mBi;
public PDFGraphic(Context context, AttributeSet attrs){
super(context,attrs);
setPageBitmap();
setBackgroundColor(Color.TRANSPARENT);
}
public void uiInvalidate() {
postInvalidate();
}
public void setPageBitmap() {
mBi = Bitmap.createBitmap(100, 100, Config.RGB_565);
mCan = new Canvas(mBi);
mCan.drawColor(Color.RED);
}
public void onDraw(Canvas canvas) {
Paint paint = new Paint();
canvas.drawBitmap(mBi, 0, 0, paint);
}
}
And this is my xml file(pdfview):
<?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="vertical">
<RelativeLayout android:id="#+id/relativeLayout1" android:layout_width="match_parent" android:gravity="bottom|center" android:layout_height="wrap_content" android:minHeight="30px" android:visibility="visible">
<com.shawnprojectPDF.PDFGraphic android:id="#+id/pdfview1" android:layout_width="match_parent" android:layout_above="#+id/editText1" android:layout_alignParentTop="true" android:layout_height="match_parent"></com.shawnprojectPDF.PDFGraphic>
<ImageButton android:layout_height="wrap_content" android:layout_width="wrap_content" android:src="#drawable/leftarray" android:id="#+id/left" android:layout_alignParentBottom="true" android:layout_marginLeft="68px"></ImageButton>
<EditText android:id="#+id/editText1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="#+id/left" android:layout_alignParentBottom="true" android:gravity="center" android:width="100px" android:singleLine="true" android:maxLength="12"></EditText>
<ImageButton android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="#+id/right" android:src="#drawable/rightarray" android:layout_toRightOf="#+id/editText1" android:layout_alignParentBottom="true"></ImageButton>
</RelativeLayout>
</LinearLayout>
In my main activity,if setContentView(R.Layout.pdfview), the view(PDFGraphic) will not be invalidated, if setContentView(New PDFGraphic(this)),it invalidates successfully.
How to refresh the view in the whole layout.
I don't see the problem. These are the results that I get with your code (next time, you do this part). With setContentView(R.layout.pdfview), this is the result:
With setContentView(new PDFGraphic(this, null) -- note that I used the two-arg constructor because you didn't define PDFGraphic(Context) -- this is the result:
In either case, your onDraw() is happening correctly.