Can't manage to requestFocus a Spinner - android

I've got an annoying issue with a screen. The screen consists of a bunch of Spinners one under the other, and then underneath the spinner, an EditText.
The problem is that when the screen starts, the EditText has focus, meaning that some Spinners are off the top of the screen. Try as I might, I cannot make the top Spinner start focused, either by using <requestFocus/> in the screen XML, or by using requestFocus() in code. I've attempted to do what requestFocus skipping next EditText suggests, and if I'm following the suggestion correctly, it doesn't work either.
To reproduce the issue, create a new Android project in Eclipse. main.xml is
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Spinner
android:id="#+id/spinner"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<requestFocus />
</Spinner>
<EditText
android:id="#+id/edittext"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
The activity code is
package nz.co.kb.testspinner;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
public class TestSpinner extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
View view = getLayoutInflater().inflate(R.layout.main, null);
final View spinner = view.findViewById(R.id.spinner);
view.post(new Runnable() {
public void run() {
spinner.requestFocus();
}
});
setContentView(view);
spinner.requestFocus();
}
}
Note multiple styles of requestFocus attempted.
Is this a platform bug, or am I doing something wrong?
Thanks.

I had a similar problem, I solved by doing two things:
1) I set the Spinner object on top (Within the onCreate method) just to make sure that my code gets executed first.
2) I used the following:
Spinner s1 = (Spinner) findViewById(R.id.spinner1);
s1.setFocusable(true);
s1.setFocusableInTouchMode(true);
Let me know if this helps or you need any further help.

From online documentation:
A view will not actually take focus if it is not focusable (isFocusable() returns false), or if it is focusable and it is not focusable in touch mode (isFocusableInTouchMode()) while the device is in touch mode.

In my case,this worked out.
Spinner s1 = (Spinner) findViewById(R.id.spinner1);
s1.requestFocusFromTouch();
s1.performClick();

Related

My ListView is not displayed properly - how to fix that?

My problem is that my listview just displays rectangle boxes with no options visible but when i click any item it displays list's text
Below is my xml file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="#+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true" />
</RelativeLayout>
below is my java file:
package com.example.mypc.contextmenuapp;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.*;
public class MainActivity extends AppCompatActivity {
ListView lv;
ArrayAdapter<String> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv=(ListView) findViewById(R.id.lv);
String []arr=getResources().getStringArray(R.array.myarray);
adapter=new ArrayAdapter<String>
(getApplicationContext(),android.R.layout.simple_list_item_2
,android.R.id.text1,arr);
lv.setAdapter(adapter);
}
}
Change the line :-
adapter=new ArrayAdapter<String>(getApplicationContext(),android.R.layout.simple_list_item_2
,android.R.id.text1,arr);
to
adapter=new ArrayAdapter<String>(getApplicationContext(),android.R.layout.simple_list_item_1
,android.R.id.text1,arr);
Differnce is that simple_list_item_1 has a single textview while the simple_list_item_2 has two textviews inside a subclass of RelativeLayout.
Also the arrayadapter does not fill multiple textview instances . You need to override getView() for that.
This answer will make it more clear
Note: - Since the listView is already match_parent both width and height , there should be no need for align with bottom or end or right.
Try without specifying the textview resource id like:-
adapter=new ArrayAdapter<String>(getApplicationContext(),android.R.layout.simple_list_item_1
,arr)
Since without it , it uses the default textview for displaying each item. But if you want you own textview , create a layout with textview as the root view and set it id as above and refer it in the constructor with the textview resouceId.
But in your case you do not need it , so try using without it.
Hope this helps.
In your image ,texts are very pallid. When you click one of them, the background of the item becomes dark and the white text appears.
On the other hand if you want items with one textview ,you should use ArrayAdapter, otherwise you must extend ArrayAdapter class. Here is an example:
https://github.com/codepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView

fitsSystemWindows="true" doesn't work after calling setContentView()

For an app I'm developing I wanted to reload the UI after a user input (basically resetting it completely after they made changes to it). I wanted to try avoiding destroying/recreating the activity and use setContentView() instead because it's a lot faster.
However when I do that I'm having an issue: the newly created UI doesn't respect the fitsSystemWindows="true" and part of it ends up behind the android's status bar.
I managed to boil it down to that code example to test it :
layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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/mainContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<Button
android:text="Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/button" />
</LinearLayout>
MainActivity.java
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
reloadUI();
}
});
}
public void reloadUI() {
setContentView(R.layout.layout);
}
}
When I load the app, I get the expected layout, that is a simple button on top of the screen, right below the status bar:
However, once I click the button which calls setContentView a second time (showing the same XML), the Button gets behind the status bar:
Calling mainContainer.getMeasuredHeight() to check what happens gives me 1848px on the first start of the app (on a screen that is 1920px tall, so its height is 72px less than the whole screen, 72px being the height of the status bar), but once I call setContentView again the mainContainer.getMeasuredHeight() gives me 1920px.
Am I missing something here? I could force the mainContainer to stick to a 1848px height with a 72px top padding, but I'd prefer to avoid an ugly hack like this.
So, what you want is to ask the framework to dispatch once more WindowInsets to your root view. That's precisely what ViewCompat.requestApplyInsets(View) will do:
Ask that a new dispatch of View.onApplyWindowInsets(WindowInsets) be performed. This falls back to View.requestFitSystemWindows() where available.
Applying just one line should resolve all your concerns:
public void reloadUI() {
setContentView(R.layout.layout);
// `R.id.mainContainer` is the id of the root view in `R.layout.layout`
ViewCompat.requestApplyInsets(findViewById(R.id.mainContainer));
}
I had the same problem. My solution is to change the rootView marginTop or paddingTop to adapt to the View manually.

How to prevent lifting listview when keyboard goes up

This is code MainActivity java and main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main_layout"
android:gravity="center"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="#75F575">
<LinearLayout
android:clickable="true"
android:layout_gravity="center"
android:orientation="vertical"
android:layout_width="250dp"
android:layout_height="100dp"
android:background="#C69817"
android:id="#+id/secondLayout">
<ListView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/mainListView1"/>
</LinearLayout>
</LinearLayout>
Java:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView lv = (ListView) findViewById(R.id.mainListView1);
ArrayAdapter<String> a = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1 ,
new String [] {"item1","item2"});
lv.setAdapter(a);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
When keyboard is shown, listview lifting up.How to prevent this.
Without listview - all normal(layout NOT go up).
Thank you.
UPDATE QUESTION with answer to FOliveira.
Unfortunately i can't remove java code (setSoftInputMode) in my real app. Java code must be and layout with listview must NOT GO UP. Try to remove listview, and you will see the layout not moving absolutely, Why layout with listview is moving? How prevent this according my conditions?
You need to add android:windowSoftInputMode="adjustPan" to your tag in the AndroidManifest.xml file.
The activity's main window is not resized to make room for the soft keyboard. Rather, the contents of the window are automatically panned so that the current focus is never obscured by the keyboard and users can always see what they are typing. This is generally less desirable than resizing, because the user may need to close the soft keyboard to get at and interact with obscured parts of the window.
If this option does not fit your needs, you can allways check Android documention about soft input mode
I'm using android:windowSoftInputMode="stateVisible|adjustNothing" , but this only for API higher 10(unfortunately).
Update:
After adding to listview this attributes:
android:focusableInTouchMode="false"
android:isScrollContainer="false"
I'm completely solved my problem.

Add buttons to a listactivity

I have a layout for a ListActivity. To modify the list I have used menu-options. But to remove a couple of "clicks" on the screen I'd like to add two buttons in the button of the screen that is always visible and not affected if the list is scrolled.
My problem is that I don't know how to add these buttons. I have tried a couple of solutions but the best I managed either the list or the buttons disapears from the layout. Seems that I can't get both buttons and list visible at the same time.
So my question is how to create a layout where I can have both buttons and the list?
Thanks in advance
Roland
From http://developer.android.com/reference/android/app/ListActivity.html:
“ListActivity has a default layout that consists of a single, full-screen list in the center of the screen. However, if you desire, you can customize the screen layout by setting your own view layout with setContentView() in onCreate(). To do this, your own view MUST contain a ListView object with the id "#android:id/list"”
EDIT: here is an example:
The ListActivity may be created like this:
public class ListViewTest extends ListActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] values = {"One", "Two", "Three"};
setListAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, values));
setContentView(R.layout.main);
}
}
The main.xml layout is as follows:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="#android:id/list"></ListView>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Test button"
android:id="#+id/TestButton"></Button>
</LinearLayout>

Android: failed to setContentView when switching to ListActivity

[update] I got the error, which says "Your content must have a ListView whose id attribute is 'android.R.id.list'". Appearently nothing in my xml is ListView. But is that required?
This is an follow-up issue on my previous question
android: which view should I use for showing text and image?
I read the article about creating ListView for LinearLayout. However, my following code failed at the setContentView() function when I changed "extends Activity" to "extends ListActivity", any idea why?
private TextView mSelection;
//private ImageView mImages;
static final String[] keywords = new String[]{"China", "Japan", "USA", "Canada"};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.contactLayout);
mSelection = (TextView)findViewById(R.id.ContactNames);
ArrayAdapter adapter = new ArrayAdapter<String>(this, R.layout.contactlayout, R.id.ContactNames,keywords);
setListAdapter(adapter);
}
My Layout is from this article: http://www.curious-creature.org/2009/02/22/android-layout-tricks-1/
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip">
<ImageView
android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="6dip"
android:src="#drawable/icon" />
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="fill_parent">
<TextView
android:id="#+id/ContactNames"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="My Application" />
<TextView
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:singleLine="true"
android:ellipsize="marquee"
android:text="Simple application that shows how to use RelativeLayout" />
</LinearLayout>
I think you misunderstood the other posts I showed you in the previous question. They were explaining how to use a custom layout for each row in your list, not how to define the entire layout file for the activity. You need something like this:
(main.xml)
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:cacheColorHint="#00000000"
android:id="#android:id/list">
</ListView>
Note the very important line android:id="#android:id/list". You must have that in your ListView as that's what tells Android where your list is. The cacheColorHint is useful if your background isn't black - see this post for more details about that.
With the above lines you can give your activity a list that will be recognised properly. Here's a basic example:
public class TestProject extends ListActivity {
final static String[] ITEMS = {"blah", "floop", "gnarlp", "stuff"};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.listrow, R.id.textview, ITEMS);
setListAdapter(adapter);
}
}
Then the listrow layout is just this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textview"/>
</LinearLayout>
This is a really simple layout. If you want to get something more complicated, changes are you'll have to use a BaseAdapter, as that gives you calls getView(...) before each row. In that you can use different layouts depending on the contents of each row. However, BaseAdapter looks scary when you first try it, so be warned! :)
Yes, if you are using a ListActivity, you need to have a ListView who's id is android.R.list in your layout file.
If you aren't using a ListView in your layout, and I don't see one in there, then switch to using a regular Activity.
Actually, your (custom) layout doesn't need a ListView when using a list activity. The easy way to solve this is just remove the setContentView() line altogether. In simple terms, when you do it, Android "assumes" the layout you're using to contain a single full-screen ListView, and provides it for you.
If you want a different (richer) interface for the Activity though, you must code the XML and use the informed ID for Android to know how to show the list implied by the activity being a ListActivity after all. Note that the layout for an item isn't the same as the list, and although I haven't tried that, I assume you can have a custom item layout without having an explicit ListView in the activity layout.

Categories

Resources