Hey all thanks for looking this through.
I really can't understand why this happends, though it might have something to do with my background thread which is processing audioinput.
All works fine until i tilt the phone, havn't yet put an landscape portrait or stuff like that in. So it should automatic just stretch my portrait layout.
But it does just stretch it, it also resets my label, and makes me unable to use my setText features on them. I also noticed that it pauses my background thread.
Here is code to set the textViews:
private void reactOnAudioMessage(Message msg) {
TextView txtVwLastValue = (TextView) findViewById(R.id.txtVwLastValue);
String result=null;
DataFile newData=null;
Bundle bndl=msg.getData();
// ** newData getting created, with the correcy value etc this is not the problem.
if(newData!=null){
txtVwLastValue.setText("Last Value Received:" +newData.getValue());
mDataList.add(newData);
drawGraph(mImageView);
}
}
Here is my xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="#+id/layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Record"
android:id="#+id/btnRecord">
</Button>
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Last Value Received:" android:id="#+id/txtVwLastValue"></TextView>
<TextView android:text="TextView" android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="#+id/txtVwType"></TextView>
<ImageView android:src="#drawable/icon" android:layout_width="fill_parent" android:id="#+id/imgViewGraph" android:layout_height="300px"></ImageView>
</LinearLayout>
So it should automatic just stretch my portrait layout.
This is not entirely true, as you have also seen. The expected behaviour for an unhandled orientation change is to recreate the Activity (which means going through the entire Activity lifecycle, onDestroy(), onCreate() and so forth - obviously the reason your label is being reset). This can be handled in various ways:
http://developer.android.com/guide/topics/resources/runtime-changes.html &
http://developer.android.com/resources/articles/faster-screen-orientation-change.html
I "handle" orientation changes in 2 rather simple ways in my application. One activity is locked to portrait (as it makes no sense to view it in Landscape) by setting the screenOrientation flag in the Manifest:
<activity android:name=".SettingsActivity" android:screenOrientation="portrait">
The 2nd Activity that I use needs to be viewed in both ways as it contains a graph that looks best when viewed in Landscape. This basically means that I make sure that my Activity closes down gracefully (including any threads or handlers that I use) and is remade to draw the graph filling the screen in Landscape orientation.
You need to think about how you wish to handle the orientation change. What makes the most sense in your application? There's a lot of good resources around that talks about orientation changes through Google.
I imagine the trouble you are having with the background thread is due to handlers that you have in the Activity which is destroyed and remade.
When the device is rotated, it effectively destroys and re-creates your activity in the new orientation. If you are kicking off your thread as part of your activity, that would explain some of the behaviour that you're seeing. If you want your thread to survive between the two activity instances, then you'll need to implement it as a Service rather than a simple thread.
The way to prove this is to set a breakpoint or add some logging in your onCreate method, and you'll see this being hit both when the app starts up and the activity is first displayed, and on device rotations.
Each time you tilt your phone, i.e each time you change between portrait mode and landscape mode, the activity restarts, so onCreate() is executed.
Related
I want to create a dynamic login screen that includes a decorative branding image when the screen is sufficiently tall but excludes the image on short screens. When the keyboard appears, it's likely the image will need to be removed. When the keyboard is hidden, the image can come back.
With a web page, I'd just use CSS media queries for the device height, show or hide the image appropriately, and it would all work nicely. I don't think anything that simple and clean is possible for an Android view, is it? So I figure I need to know the height of the window when the activity is created and create the view appropriately.
In the manifest, I've set my main activity to adjustResize when the keyboard appears. When the keyboard appears, my view does resize but my activity is surprisingly not recreated. When the screen is rotated, the activity is recreated.
The documentation says the view will be recreated when the keyboard availability changes. The first paragraph from https://developer.android.com/guide/topics/resources/runtime-changes
Some device configurations can change during runtime (such as screen orientation, keyboard availability, and when the user enables multi-window mode). When such a change occurs, Android restarts the running Activity ( onDestroy() is called, followed by onCreate()). The restart behavior is designed to help your application adapt to new configurations by automatically reloading your application with alternative resources that match the new device configuration.
My questions are
What's the best way to handle my design goal?
Why is my activity not recreated when the keyboard appears?
Below are the relevant parts of my test app. There is no image in this as I didn't even get that far before running into what seems like behavior contradicting the documentation.
AndroidManifest.xml
<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Log.d("MainActivity", "onCreate")
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
activity_main.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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/intro"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:text="Top"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="#color/colorAccent" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/intro"
android:singleLine="true" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:text="Bottom"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="#color/colorAccent" />
</android.support.constraint.ConstraintLayout>
The activity isn't recreated when the keyboard appears because that isn't how Android works. Its not supposed to be. (Although if you have an old fashioned device with a slide out physical keyboard it will be recreated when you slide it out, because its treated as a hardware configuration change). Keyboards being shown/hidden is done without recreation. Which is a good thing, that many recreate events would be expensive given how many people just shove a ton of logic into onCreate.
How to do what you want- you can't. There is no API to detect when the keyboard is opened. There are commonly used hacks that attempt to discover it, but they're all flawed (they can have problems with split screen mode, picture in picture mode, multiple screens, and keyboards which are too small, because they all work based on guessing based on height changes).
The method OnFocusChangeListener() will detect whenever a View gains or loses focus. EditText makes the keyboard show up whenever it gains focus. Therefore, you should attach a OnFocusChangeListener() to those EditText that you want:
EditText myET = (EditText)findViewById(R.id.myET);
myET.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus) {
//Hide image
} else {
//Reveal image
}
}
});
Moreover, to hide and reveal the image you should use the property called visibility.
The methods are:
myImageView.setVisibility(View.VISIBLE); //This will show the Image
myImageView.setVisibility(View.INVISIBLE); //This will make the Image invisible
myImageView.setVisibility(View.GONE); //This will make the Image invisible, and also it will collapse the layout, occupying no space at all.
Don't try using INVISIBLE and GONE simultaneously, since that could cause some trouble. In your case, from what I understand you might want to use GONE and VISIBLE.
The only problem with this approach is that if you have multiple EditText, you would have to set up many times the same code. To solve that, please refer to the following link:
EditText setOnFocusChangeListener on all EditTexts
I've been searching for an answer and I came across this:
https://developer.android.com/training/keyboard-input/visibility#java
It says android DOES do what you want.
I just tried it, add 1 line, ONE LINE!, to your manifest and it works.
Oh wait... you want the brand to disappear... hmmm well with this it wouldn't have to?
DOH! You already knew about that.....
"What you want to do you can't"...
I don't know how to do it, but I disagree that it can't be done. I have the PayPal app and when the keyboard appears the login button and the rest of the login screen resize so that the login button isn't covered by the keyboard. How they're doing it, I don't know, but obviously somehow the app knows the keyboard appears and adjusts accordingly.
I've been searching for an answer and I came across this:
https://developer.android.com/training/keyboard-input/visibility#java
It says android DOES resize the screen when then soft keyboard appears/disappears.
I just tried it, add 1 line, ONE LINE!, to your manifest and it works.
I have an activity with four buttons, when i play it on the emulator everything is OK, but when i test it on my mobile the buttons grow bigger or actually the background or the screen gets smaller but the buttons stay the same, so it looks bigger.
Can i make the buttons adapt with the screen the same way the background of the activist do?
Here is my xml file
<?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"
android:background="#drawable/mainn"
android:gravity="top" >
<Button
android:id="#+id/b_labor"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="114dp"
android:background="#drawable/labb" />
<Button
android:id="#+id/b_mosul"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_above="#+id/b_labor"
android:layout_alignLeft="#+id/b_labor"
android:layout_marginBottom="32dp"
android:background="#drawable/ninaa" />
<Button
android:id="#+id/b_trafic"
style="#style/Theme.Transparent"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_above="#+id/b_mosul"
android:layout_alignLeft="#+id/b_mosul"
android:layout_marginBottom="28dp"
android:background="#drawable/traficc" />
<Button
android:id="#+id/b_nati"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_above="#+id/b_trafic"
android:layout_alignLeft="#+id/b_trafic"
android:layout_marginBottom="34dp"
android:background="#drawable/natiii"
/>
I think you are new to Android so you need to learn several things before creating UI elements on android devices. UI is not simple to create you should understand different concepts to create complex GUI in Android. The main problem in your above case is each device have different resolutions and if you Hard code your button then it will not adapt according to your device resolution and screen size. So before creating any UI element you need to keep some of the points in your mind:
Never try to hard code anything specially GUI parameters because these can change according to devices.
Always create and update your GUI from UIThread only.
Use asynchronous tasks, services and threads to perform heavy tasks and background tasks.
Always try to keep UI thread with minimum load.
To learn more about GUI characteristics try to explore LayoutParams for different layouts and views.
There are lot more thing you need to learn. According to me while creation of GUI you should start from Relative layouts and try not to use Absolute layout ever.
You can check below links for some help:
https://stackoverflow.com/questions/2992754/ui-design-tips-and-tutorials-for-android
http://mobile.smashingmagazine.com/2012/07/26/android-design-tips/
As we all are aware of different screen sizes of android devices , We should check for the alignment of buttons in different devices , For start check this link Developer.google
There is stackoverflow answers , that will help you
screen size vs button position
I was hoping someone here might have an idea what causes this sort of behaviour:
Throughout my application, in seemingly random places and in random conditions I'm observing this strange UI issue. Images are on occasion being loaded black (with the correct bounds) or with the incorrect image source (again, with the correct bounds). This effects ImageViews and has effected android:background tags with references to colour resources.
My application relies on 6 library projects, it runs Native Code via a Service and Activities in the App use GlSurfaceViews (although, not all Activities which display the problem contain OpenGL components). The problem could I suppose be from any of these places or a combination of them through using large amounts of memory.
You can see this behaviour in the following screen shots:
This is actually a 6 or so pixel wide column separator image which has been incorrectly drawn into my ImageView (the ImageView seems to have correctly sized itself).
When going out of the Application and then back in again (repeatedly) it instead appeared (and remained) like so:
After a Force Clear and a Clear App Data it returned to the correct format:
As you can also see the Magnifying Glass image next to it is displaying fine in each of these. The problems with these missing/incorrect images and backgrounds seems to happen randomly, throughout the application lifecycle, and I've been unable to find a way of reproducing it.
The layouts for these images are nothing special, I'm not doing anything funny during the rendering lifecycle (i'm not overriding onDraw() or onMeasure() or the like). The source of these images aren't being set dynamically but via the XML.
As you can see from the above example, it's not a build issue as it occurs between app lifecycles not between installs. It's also happening on different devices, Samsung 8.9, Acer Iconia Tab, Motarola XOOM,
It seems to me to be some sort of error with the reference table, could it perhaps have been nudged by my native code? Or is it an effect of me in some stages of the application using too much memory?
Here's the XML source for the above example:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/browseProgressWrapper"
android:layout_width="match_parent"
android:layout_height="#dimen/actionbar_compat_height"
android:orientation="horizontal">
<RelativeLayout android:layout_width="#dimen/search_bar_width"
android:layout_height="match_parent">
<EditText android:id="#+id/browseFilter"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="4dp"
android:layout_marginLeft="5dp"
android:imeOptions="actionSearch"
android:background="#drawable/edit_text_blue"
android:maxLength="30"/>
<ImageView android:id="#+id/clearSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="#drawable/ic_input_delete"
android:layout_marginRight="5dp"/>
</RelativeLayout>
<ImageView android:id="#+id/browseFilterButton"
android:src="#drawable/ic_menu_search"
android:scaleType="center"
android:layout_width="#dimen/actionbar_compat_height"
android:layout_height="#dimen/actionbar_compat_height"
android:layout_gravity="center_vertical"
android:minWidth="#dimen/actionbar_compat_height"/>
</LinearLayout>
A more full description of the code / layout surrounding another such occurrence I happened to get the screenshot for:
I have a "Settings" Activity which restarts my app after saving new settings details. It does this by stopping a Service, calling a new Activity (the Splash Activity) and finishing itself:
mConfiguration.save();
mConfiguration = new Configuration(Configuration.getInstance());
getActivity().stopService(new Intent(getActivity(), NativeService.class));
getActivity().finish();
startActivity(new Intent(getActivity(), SplashActivity.class));
Most of the time (and on most devices) this works fine, the Splash Activity contains an image which loads correctly. Sometimes though on some devices the Splash Activity loads either an incorrect resource (what my testers refer as "an upside down Nike tick") or just a blank box (as seen below). Does anyone know why?
Here is the Layout for the Splash page, as you can see it's pretty simple, no surprises:
<?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:background="#color/ContentBackgroundColor"
android:orientation="vertical" >
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="2" />
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="#drawable/manager_android_400" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<ProgressBar
style="#android:style/Widget.ProgressBar.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="2" />
</LinearLayout>
Theory tested and debunct:
I've theorised that this could be a processor/memory issue where the Layout isn't being drawn fully before the Splash screen exits and moves onto the next Activity so I put in this piece of code:
image = (ImageView) findViewById(R.id.image);
image.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
image.getViewTreeObserver().removeGlobalOnLayoutListener(this);
moveToStartScreen.start();
}
});
The hope was the code above would make sure the Image is definitely loaded before moving onto the Start page but seems to have had no observable effect.
Another Theory
I was also wondering if this could be being caused by the R.id / R.colour / R.drawable resources some how being currupted in program execution? Does anyone know why that might happen.
Could my native code be running rampant on some memory addresses that Android isn't correctly allocating?
Has anybody noticed this before - or perhaps know why this behaviour occurs?
Graeme, I had almost the same problem and found out that it was a reported bug of the android plattform. It was corrected in the 3.0 version I think. Which API are you compiling with? Try to build with the last available api and be sure to compile with JDK 1.6
If your problem is related to this bug, this should fix the problem.
This is a simple problem of refresh, clean, and rebuild.
Images in your various drawable folders or resource id indices are out of sequence because they were either changed outside of the eclipse IDE (via external source control such as GIT, SVN or other edits) and not refreshed in the eclipse navigator. Or, the files may have been updated in a library project upon which your UI Activity depends.
I have found that although .java file dependencies are propagated throughout the system, this is not always the case for resources such as images and .xml files.
The solution is fairly simple, clean everything, refresh all of your projects, and rebuild. The stretched or black edges should be gone.
Note: The predominant manifestation of this problem occurs when 9-patch images become treated like standard .png images. This means that they get stretched in a linear manner across the image instead of just at the edges. To me, this explains your 'Torn/Stretched' example. I have seen similar often. Another common manifestation is that text strings occasionally get displayed with the wrong resources!
I have an image in portrait mode, which is displayed correctly. When I change the configuration to landscape, the image is not displayed.
Note that the LinearLayout, enclosing the ImageView is displayed right(I checked it by changing the background). But when I changed the background for the ImageView, the background was also not shown.
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="10dp" android:layout_weight="3">
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical" android:minHeight="48dp" android:minWidth="48dp" android:src="#drawable/xyz" android:id="#+id/img"/>
Do you have different files specified for portrait and landscape more? I.e., do you have a layout file with the same name in the layout folder as well as the layout-land folder? If so, make sure both files include the ImageView.
You are most likely specifying the file you want to display like
myImageView.setImage("myfile.jpg");
in your onCreate method.
Move this code to onResume (create onResume with the #Override if you do not already have it) This will fix your problem
OK, your layout file is unnecessarily large and complex. So let's try a couple of things-
First, try creating a simple version of your XML file that contains the barebones for displaying the image. If that works in both portrait and landscape, you know that the problem is not your activity or your image.
If the first step works, the next step would be to work on simplifying your layout file, there is a lot that could be pruned. It goes seven layers deep at points, that should almost never happen. Here is a good blog post by an Android engineer on better layout design. You can find similar resources elsewhere.
I have an Activity in a tablet app and I want to show different Fragments depending on the orientation. I figured the easiest way to do this was just to define two different layout XML files, one for landscape and one for portrait. In other words I have /layout/home.xml which looks like this:
<LinearLayout android:orientation="horizontal">
<fragment class="com.foo.app.Frag1" android:id="frag1"/>
<fragment class="com.foo.app.Frag2" android:id="frag2"/>
</LinearLayout>
And then in /layout-port/home.xml:
<LinearLayout android:orientation="vertical">
<fragment class="com.foo.app.Frag2" android:id="frag2"/>
<fragment class="com.foo.app.Frag3" android:id="frag3"/>
</LinearLayout>
When I run it, I can start in landscape and go to portrait, and everything is fine. However, when I go from portrait to landscape, the app crashes with a android.content.res.Resources$NotFoundException with Resource ID equal to "frag3." That's right it's looking for Frag3 when going to landscape made, and there is no Frag3 in that mode. This happens during the Activity.onCreate stack, so before any of my code has any chance to make the app crash.
Are Fragments not supposed to work this way? Do I need to use a FragmentTransaction instead?
It's hard to say without seeing the code- However, Resources.NotFoundException usually means you tried to look up an asset (think R.layout.xx, R.drawable.xx, etc) incorrectly.
That said, I tried writing a small app using your layout XML, and the compiler yelled at me for hardcoding strings as the ID's when I copied in your XML code to test it out. Try switching the values of the android:id attribute to read like this:
android:id="android:id="#+id/frag1"
that might fix the issue.