Hey I really need your help.
My problem is that Android Studio will not display the Layout correctly in the emulator or physical device.
Whenever i place a textView, button etc. and i want to center it (horizontally, vertically or both), and i start the emulator it's stuck to the top left corner.
This is my code::
private void firstStage(){
ViewGroup container = (ViewGroup) findViewById(R.id.container);
container.removeAllViews();
container.addView(getLayoutInflater().inflate(R.layout.first_stage, null));
}
private void showHint(){
ViewGroup container = (ViewGroup) findViewById(R.id.container);
container.removeAllViews();
container.addView(getLayoutInflater().inflate(R.layout.first_hint, null));
firstImage = (ImageView) findViewById(R.id.hintImage);
firstImage.setImageResource(R.drawable.firsthint);
Button back = (Button) findViewById(R.id.first_hint_backButton);
back.setOnClickListener(this);
}
In the showHint Method everything works fine.. the button and imageview are there where i have set them.
In the firstStage method however i have a textView and it is always in the top left corner if I choose something with "center", like Android Studio suddenly can't handle gravity:center anymore.
I tried it with creating a new project but the error still occurs. If i set the textView to the right side and then put it in the middle with margin-right, it works. But that is not really a long-term solution. Did anyone of you experience the same problem?
And before you ask, Yes i have tried everything with "center". In the XML- file, in the code and so on.
Maybe this will also help you::
If i call the layout via setContentView(R.layout.first_stage); it works. The textView is right in there where i want it to be.. I just don't know why it won't work with ViewGroup anymore, when it works perfectly for my other 2 Layouts?!
This is my Layout-Code::
<?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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="#string/first_stage"
android:id="#+id/textView2"
android:enabled="true"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
/RelativeLayout
EDIT::
It works now!! I changed the container from being a RelativeLayout to a FrameLayout. I don't know exactely why it works now, but it works!!!
Thanks to pdegand59 for the fast help, really appreciate it.
When inflating a view, you have to give a parent to the inflater to resolve the layout params of the view.
container.addView(getLayoutInflater().inflate(R.layout.first_stage, container, false));
That's why Android Studio has a warning when inflating with null parent.
By the way, you can add the inflated view automatically to your view hierarchy with only :
getLayoutInflater().inflate(R.layout.first_stage, container, true);
Related
I'm trying to make the whole screen clickable so I'm trying to set an id for a layout and find it in java class. When I do this, it says incompatiable types (layout vs a view). I understand they are different types but upon googling this, several posts have suggested selecting the layout in an activity in this manner. They can make a call such as this -
RelativeLayout theLayout = (RelativeLayout) this.findViewById(R.id.Layout)
and they don't seem to be getting this error.
Another stackoverflow post with this - onTouchListener for entire screen
My code referencing this is below -
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:id="#+id/thelayout" >
<TextView android:text="This will change with speech" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/textview"/>
</RelativeLayout>
And in activity -
RelativeLayout theLayout = this.findViewById(R.id.thelayout);
Am I missing somethinng?
Instead of this,
RelativeLayout theLayout = this.findViewById(R.id.thelayout)
Try this in your Activity,
RelativeLayout theLayout = (RelativeLayout) this.findViewById(R.id.thelayout)
Instead of using setContentView(int layoutResID) with the layout id, inflate the layout get the view reference and then use the setContentView(View view).
View layout = View.inflate(context, R.layout.theLayout, null)
setContentView(layout)
You don't need to cast the layout to RelativeLayout, as you can add the click/touch listener to a View class.
wonder if anyone has came across this problem before. I have an app which detects faces and places touchable squares around the faces, all in a RelativeLayout. When touched I want to add some text into the View which is all working nicely, but when I go to simply add a background to the TextView it just does nothing. I've tried a standard background setBackgroundColor(Color.WHITE); instead of the background I really want to use (setBackgroundResource(R.drawable.nametag);) and still nothing.
TextView nameLabelView = new TextView(activity);
nameLabelView.setText(fullname);
nameLabelView.setTextColor(Color.BLACK);
nameLabelView.setBackgroundColor(Color.WHITE); //TODO <-- wth??
//nameLabelView.setBackgroundResource(R.drawable.nametag);
nameLabelView.setGravity(Gravity.CENTER_HORIZONTAL);
//duplicate layout params from active face View so label sits inside it
ViewGroup.LayoutParams lp = selectedFaceView.getLayoutParams();
nameLabelView.setLayoutParams(lp);
facePreviewLayout.addView(nameLabelView);
Strange one, hope it's obvious to someone out there, thanks in advance!
I have tested your code and it works ok for me. It is necessary to provide more information so I can help more with it. The code below works fine.
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView nameLabelView = new TextView(getApplicationContext());
nameLabelView.setText("Test");
nameLabelView.setTextColor(Color.WHITE);
nameLabelView.setBackgroundColor(Color.BLACK); //TODO <-- wth??
//nameLabelView.setBackgroundResource(R.drawable.nametag);
nameLabelView.setGravity(Gravity.CENTER_HORIZONTAL);
//duplicate layout params from active face View so label sits inside it
FrameLayout selectedFaceView = (FrameLayout)findViewById(R.id.frame_layout);
ViewGroup.LayoutParams lp = selectedFaceView.getLayoutParams();
nameLabelView.setLayoutParams(lp);
RelativeLayout facePreviewLayout = (RelativeLayout)findViewById(R.id.relative_layout);
facePreviewLayout.addView(nameLabelView);
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/relative_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#+id/frame_layout"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#00FF00" >
</FrameLayout>
</RelativeLayout>
Thank you janzoner for your test really appreciate it, good to know I wasn't going mad. I've found a way to work around it though, I have no idea why this method works and the setup I had before didn't, perhaps I'd been staring at it too long and missed something somewhere else.
Basically beforehand I was adding the name label TextView into the main RelativeLayout (whose children were the actual image and all the face Views etc).
Now I have moved the name label TextView into its own RelativeLayout which sits around the face, and that's magically done the trick. This is a cleaner way of doing things anyway as you can't iterate through child Views of Views but you can children of RelativeLayout's and I will need this later!
Phew!
I have a LinearLayout that contains a TextView, and always will. There will also always be at least one button located below the TextView, but there might be more than one under certain circumstances.
I can successfully create and add as many buttons as I need programmatically. I can also successfully set whatever appearance related parameters/options that I require for these buttons programmatically.
The problem is that I don't know how to tell a programmatically created button that it should use a XML resource file, which contains the appearance and layout parameters, instead of setting these parameters programmatically.
I've looked at similarly named questions and spent time messing with the API itself, to no avail.
Edit:
Here's an approximation of what I'm trying to do that will hopefully make explanations a bit clearer for me:
private TextView textView;
private SomeObject someObject;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View scrollView = inflater.inflate(R.layout.fragment_play_game, container, false);
textView = (TextView) scrollView.findViewById(R.id.game_data_text);
textView.setText(someObject.getTextForTextView());
LinearLayout layout = (LinearLayout) scrollView.findViewById(R.id.game_data_container);
for (String optionText : someObject.getTextForButtons()) {
layout.addView(createOptionButton(optionText, layout));
}
return scrollView;
}
private View createOptionButton(String optionText, LinearLayout layout) {
Button optionButton = new Button(this.getActivity());
// set button layout/options here, somehow??
optionButton.setText(optionText);
return optionButton;
}
My XML layout file for the fragment looks like this (It's this LinearLayout that I'm trying to add buttons to):
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/game_data_container"
etc... >
<TextView
android:id="#+id/game_data_text"
etc... />
</LinearLayout>
</ScrollView>
Also, if I'm to create an XML layout file for the button (lets call it custom_button.xml) should it look something like this?:
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/play_game_option_button"
etc... />
Update:
Just to expand a bit on what MrFox# is talking about, what I did to get it working was replace this line:
Button optionButton = new Button(this.getActivity());
with this one:
Button optionButton = (Button) inflater.inflate(R.layout.play_game_option_button, layout, false);
...which inflates an xml file containing only a Button layout (the button template). In this case, it returns the root view of that file, which is just the button because there's no parent above the button in the file.
However, if I had have set the last boolean value (attachToParent) to true, it would have returned the root container that the button will be in (which is just the 'layout' variable that was passed into the call).
I can now produce as many buttons as I want using this template.
Have you thought of making a layout that is just the button with the applied XML styles and then inflating it into your linear layout?
something like:
inflater.inflate(R.layout.StyledButton, MyLinearLayout, true);
xml for your button under /res/layout/my_button_layout.xml
<Button xmlns:android="http://schemas.android.com/apk/res/android"
... />
code in your activity
myButton = (Button)inflate.inflate(R.layout.my_button_layout, null);
myView.addView(myButton);
I recently updated a custom view so I could potentially add an EditText to the center of my canvas (so to speak).
After adding my onDraw code to dispatchDraw my custom LinearLayout works in the same way as my previous custom view did.
Now, how can I add an EditText smack in the middle of the layout?
So far I am trying this:
EditText edit = new EditText(getContext());
edit.setText("My EditText");
edit.setTextSize((int)Math.ceil(thickness/2));
edit.setWidth((int)(diameter*0.07f));
edit.setX(centerX);
edit.setY(centerY);
addView(edit);
Forgive some of the variables, they are not too important but I'm trying to add the EditText using the X and Y coordinates.
Thanks for any help.
UPDATE:
I have updated my LinearLayout constructor to inflate the comment_edit.xml file to see if I could get it to work this way.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_comment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="#+id/edittext_comment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="text"
android:imeOptions="actionDone" />
</LinearLayout>
The LinearLayout constructor extract is as follows:
LayoutInflater inflater = LayoutInflater.from(context);
LinearLayout view = (LinearLayout) inflater.inflate(R.layout.comment_edit, this, false);
EditText edit = (EditText) view.findViewById(R.id.edittext_comment);
edit.setText("Add Comment");
edit.setX(112);
edit.setY(117);
addView(view);
I have also tried:
LayoutInflater inflater = LayoutInflater.from(context);
LinearLayout view = (LinearLayout) inflater.inflate(R.layout.comment_edit, this, false);
EditText edit = (EditText) view.findViewById(R.id.edittext_comment);
edit.setText("Add Comment");
view.setX(112);
view.setY(117);
addView(view);
The EditText still does not appear
In case the answer is not found yet. Every dynamically created view should have layout parameters (WRAP_CONTENT, FILL_PARENT, etc) that is why is not shown. For more information please edit your question accordingly.
An example might be:
editText.setLayoutParams(new LayoutParams(WRAP_CONTENT,WRAP_CONTENT));
EDIT:
Now your problem is that the edit text is not centered. Ok, I can give you an overview but I believe you must research from now on because there are a lot of things to do. First of all the LinearLayout is what it says, is a layout that it stacks the views vertically or horizontally. The position of the text shouldn't be given with the actual pixels of the screen but with some other specific layout parameters. Take Gravity for example, it aligns the inner view of a layout to the center, left, etc. Add gravity property of the LinearLayout.
I hope it helped
I have a very strange problem with Android animations, I tried many different approaches and components, and still couldn't find any explanation.
I have a FrameLayout which is a container for views, and a Button.
This FrameLayout should display only one view at a time, and when I click on the Button, I want the FrameLayout to display another view, and start an animation on the view that is removed from the FrameLayout.
The specificity here is that I only use two views, and I want to switch between these two views.
The problem:
When I click the button multiple times really fast, and then stop clicking, the two views are shown at the same time one on top off the other, and won't disappear. The container still contains only one view though... definitely strange!
error screenshot http://i.minus.com/jDXyvUsE1LCOx.png
I was able to reproduce this with a simple example:
public class TestAnimActivity extends Activity implements OnClickListener {
private FrameLayout container;
private TextView current;
private TextView next;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
current = new TextView(this);
current.setText("View 1 YEAH");
next = new TextView(this);
next.setText(" View 2 DOH");
container = (FrameLayout) findViewById(R.id.container);
container.addView(current);
findViewById(R.id.button).setOnClickListener(this);
}
public void onClick(View v) {
Animation outAnimation = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
current.startAnimation(outAnimation);
container.addView(next);
container.removeView(current);
TextView temp = current;
current = next;
next = temp;
}
}
As you can see the animations are being started on the views while previous ones are still running, and the way I do that may somehow be the source of the problem.
If I comment the animation related code, it works perfectly:
// Animation outAnimation = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
// current.startAnimation(outAnimation);
If I stop reusing views and create new views instead, it also works perfectly:
// next = temp;
next = new TextView(this);
next.setText("View: " + new Random().nextInt());
But I don't want to create new views :-) .
It seems that the problem is related to starting animations several times on a view while adding / removing this view from its parent.
I first tried with a ViewFlipper, then a ViewAnimator, then looked up the Android source code and ended up doing this manually to reproduce the problem.
If you want the layout to be able to test by yourself, here is my main.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" >
<FrameLayout
android:id="#+id/container"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:id="#+id/button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Click me fast" />
</LinearLayout>
Thank you for your time!
I finally found a way to fix the issue.
When we remove a view from a ViewGroup, if there is an animation running on this view, it is automatically added to the "disappearing children" list of the ViewGroup.
The issue seemed to appear when we tried to add to the ViewGroup a view that has been removed from it but was still in its disappearing children.
There's an easy way to fix that : viewGroup.clearDisappearingChildren();
Here would be the new implementation of the onClick() method :
public void onClick(View v) {
next.clearAnimation();
container.clearDisappearingChildren();
Animation outAnimation = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
current.startAnimation(outAnimation);
container.addView(next);
container.removeView(current);
TextView temp = current;
current = next;
next = temp;
}
If it works without quickly pressing the button, and works without the animation then you may be seeing how animations actually work. From my understanding what is displayed in the animation is separate from the View objects they are animating. You can try animating from the parent view instead of the ones that keep being added and removed. Or make sure to clean up the animation before removing the view, as it sounds like the view isn't able to get the onAnimationEnd method where it can remove the phantom image being displayed (setFillAfter(false) which is the default behavior of an Animation).