PreferenceFragment faults on id.list but not on id.content - android

What I really want to do is add a preference screen to an existing layout with other items in it (such as a button) without using deprecated approaches. I have looked at the 'add button to preference screen' and I get that to semi-work using deprecated approaches.
I have two xml layouts. First the preference screen (at the moment the PreferenceCategory is superfluous) with 12 other CheckBoxPreferences omitted for clarity:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:key="#string/specialization_prefs"
android:title="#string/select_specializations">
<CheckBoxPreference
android:key="#string/pulse_ox_key"
android:title="#string/pulse_ox"
android:defaultValue="true" />
<CheckBoxPreference
android:key="#string/bp_key"
android:title="#string/bp"
android:defaultValue="true" />
</PreferenceCategory>
Then I have the activity layout (PreferenceActivity or Activity; does not seem to matter):
<?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:id="#+id/specializations_layout" >
<Button
android:id="#+id/btn_done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="Exit and Save" />
<ListView android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
The ListView was meant to be a dummy to be replaced with the PreferenceFragment which I got from a Stackoverflow suggestion. The Button I want to keep.
My PreferenceFragment is as follows:
public class SpecializationsFragment extends PreferenceFragment
{
#Override
public void onAttach(Activity specializationsActivity)
{
super.onAttach(specializationsActivity);
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.specializations);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return super.onCreateView(inflater, container, savedInstanceState);
}
}
Finally my PreferenceActivity is as follows:
public class SpecializationsActivity extends PreferenceActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.specializations_layout);
getFragmentManager().beginTransaction()
.replace(android.R.id.list, new SpecializationsFragment())
.commit();
}
}
If I replace the 'android.R.id.list' with 'android.R.id.content' it sort of works. I see my button but my preference screen scrolls right over it. This is what I get when I follow the deprecated button solution. If I use the 'android.R.id.list' instead, the application crashes saying "addView(View) is not supported in AdapterView.
I have searched on that problem as well. What am I missing? This code currently does nothing but a GUI display. What do I need to add to get the button to display and the preference screen to scroll in the space below it as it is supposed to do in its own 'fragment'? I thought that was the whole idea behind fragments. (Yes they actually work quite well as long as preference screens are not present.) It also makes no difference using the 'add' method versus the 'replace' method.

For anyone who cares I found a solution. Not what I expected but it worked. First I needed to nest a layout within my layout. Then I needed to align this nested layout below the button. I also needed to have the dummy ListView in there but I do not know why. So the xml appears as follows:
<?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" >
<Button
android:id="#+id/btn_done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="Exit and Save" />
<RelativeLayout
android:layout_below="#+id/btn_done"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/specializations_layout" >
<ListView android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
</RelativeLayout>
The code now has the replace method (using 'add' or 'replace' made no difference) using the id added to the nested relative layout as follows:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.specializations_layout);
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(R.id.specializations_layout, new SpecializationsFragment())
.commit();
findViewById(android.R.id.list).setBackgroundColor(Color.argb(0, 0, 0, 0));
}
I don't understand what is going on under the hood here, especially with the need for the dummy element and its android:id/list attribute. I would like to have seen it work without the ListView element as I believe would be the case if this was an ordinary fragment and not a preference screen. I would be grateful to anyone who can explain this to me!

Related

including the content from 2 activities in 1 activity

I have 2 activities (lets call their layouts activity_one and activity_two). Both with seperate XML templates and seperate Activities.
in the onCreate(Bundle savedInstanceState) of one of them I am calling setContentView(R.layout.activity_one);
One of the subviews in this layout is a LinearLayout. I want to put the content of R.layout.activity_two within this LinearLayout and if possible use the code from its activity class (the onClickListeners etc).
The reason I want to do this is that the Tablet version of the app I am building should show data from both views.
Is this possible? How would I do this?
Thanks :).
You should use fragments for that, with fragments you will be able to have two separate layout files, two separate fragments - which will be quite similar to your current activities (its quite easy to convert activity to fragment), and also you will need additional activity that will include in itself those two fragments.
You can still have your current activities showing their layouts, just create FragmentActivity for each such activity, and show apropriate fragment.
Other solution might be with using layout include tag, that allows to include one layout into another.
btw. fragments were introduced to make it easier to build tablet versions (big screen) of application, while still being able to show UI version for phones (smaller screen).
// try this way here i just gave simple demo
**activity_one.xml**
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="match_parent">
<Button
android:id="#+id/btnActivityOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Activity One"/>
<include
android:layout_width="wrap_content"
android:layout_height="wrap_content"
layout="#layout/activity_two"/>
</LinearLayout>
**activity_two.xml**
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="#+id/btnActivityTwo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Activity Two"/>
</LinearLayout>
**MyActivity.java**
public class MyActivity extends Activity {
private Button btnActivityOne;
private Button btnActivityTwo;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_one);
btnActivityOne = (Button) findViewById(R.id.btnActivityOne);
btnActivityTwo = (Button) findViewById(R.id.btnActivityTwo);
btnActivityOne.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MyActivity.this,"Activity One Button",Toast.LENGTH_SHORT).show();
}
});
btnActivityTwo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MyActivity.this,"Activity Two Button",Toast.LENGTH_SHORT).show();
}
});
}
}
Simple work using actvities itself
For your first question
content of R.layout.activity_two within your LinearLayout
Use the <include ../> tag for that
Eg: <include layout="#layout/activity_two" /> within your LinearLayout
For your Second Question
if possible use the code from its activity class (the onClickListeners etc).
Make a class Extends Activity and add all the listeners you need in common and name the class as BaseActivity and extend BaseAcitivity instead of Activity for your 2 Activities.

RoboFragments in layout.xml

I've been trying to get Roboguice to work with fragments declared in a <fragment> block in the layout file and then injected into the activity, but, although the fragment exists somewhere off screen (an EditText in the fragment takes focus and fires events), It is not visible. Does RoboGuice support what I'm trying to do here or should I go about it a different way?
code:
<?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" >
<fragment
android:id="#+id/myFragment"
android:name="com.example.MyFragment"
android:layout_height="0dp"
android:layout_width="0dp"
android:layout_weight="1" >
<!-- Preview: layout=#layout/my_fragment -->
</fragment>
</LinearLayout>
Java:
#ContentView(R.layout.participant)
public final class Main extends RoboFragmentActivity {
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#InjectFragment(R.id.myFragment) private MyFragment myFragment;
}
Solved the issue, but for anyone else looking - The issue at hand was completely unrelated to RoboGuice, which allows fragment injection exactly as shown above. Rather the issue was that both of my layout dimensions for the fragment were set to 0dp, ensuring that my fragment would never be rendered.

need help regarding ActionBar And Fragmentation

I am using actionbarsherlock library to have action-bar in my application,
I am also using view-pager to switch between the page,
Now the problem is i want only one tab with two fragment to display data regarding each other.
What could be the possible way to do this?
I have been going through like the one below but unsuccessful
In main fragment i am inflating a xml like this
<code>
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View fragView = inflater.inflate(R.layout.album_view_main, container, false);
return fragView;
}
</code>
xml fie is look like this
<code>
<?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="horizontal" >
<fragment
android:id="#+id/fragment_album_view"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_weight="3"
class="com.nix.music.activity.fragments.AlbumFragMent" />
<FrameLayout
android:id="#+id/frame_list_song"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_weight="2" >
</FrameLayout>
</LinearLayout>
</code>
but the problem is i cannot find "frame_list_song" in AlbumFragment class it appears null
what could be the way around ?
thank you
This layout should be set in the parent activity using setContentView(). Then, you would be able to do something like getActivity().findViewById(R.id.frame_list_song) from your AlbumFragment. The better way would be to use an interface and transfer control to the main activity, and not access other fragments directly.

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.

How to implement master and child page like Activity in Android?

I want to place a common banner and menu on each Activity with footer too.
Can anyone guide me how can I implement master and child page like asp.net in Android???
Any help would be appreciated.
You could have each of your Activities extend a common base class which has a onCreateOptionsMenu method which inflates the menu from the same XML each time. Though as you can't have multiple inheritance, this may be tricky when you want to have plain activities and list activities, for example.
Another way would be to have a Util class where you have a method like setupMenu(Menu) which each of your Activities can call if you're doing some more complex menu setup.
In terms of the XML UI layout for each of your Activities, you can include a common banner by using the <include/> tag.
The solution was pretty easy.
You need to extends "Activity" Class,in onCreate function SetContentView to your base xml layout and also need to override setContentView in base Activity Class
For Example:
1.Create "base_layout.xml" with the below code
<?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"
android:background="#000000"
android:padding="15dp" >
<LinearLayout android:orientation="horizontal" android:background="#000000"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:minHeight="50dp" android:paddingLeft="10dp">
<ImageView android:layout_width="wrap_content" android:id="#+id/ImageView01"
android:adjustViewBounds="true" android:layout_height="wrap_content"
android:scaleType="fitCenter" android:maxHeight="50dp" />
</LinearLayout>
<LinearLayout android:id="#+id/linBase"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</LinearLayout>
</LinearLayout>
2.Create "BaseActivity.java"
public class BaseActivity extends Activity {
ImageView image;
LinearLayout linBase;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.base_layout);
linBase = (LinearLayout)findViewById(R.id.linBase);
}
#Override
public void setContentView(int id) {
LayoutInflater inflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(id, linBase);
}
}
and
public class SomeActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.some_layout);
//rest of code
}
}
The only thing I noticed so far was that when requesting a progress bar (requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS)) this needs to be done before calling super.onCreate. I think this is because nothing can be drawn yet before calling this function.
This worked great for me and hopefully you will find this useful in your own coding.
I've had the same problem and solved it using ActivityGroup.
I suppose that menu items will move user to another activity, so with the same menu in every activity closing application with BACK button can be almost impossible (after some time user will have to go back through all activities he had ever seen).
I haven't found any good tutorials in english so have written mine some time ago (it's somewhat too short and in polish only, but Google Tranlslated version should be understandable) check this
You can also check how the TabHost works
ViewStub is the solution
activity_masterpage.xml
<LinearLayout 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"
android:orientation="vertical" >
<ViewStub android:id="#+id/stub_content"
android:inflatedId="#+id/subTree"
android:layout_width="match_parent"
android:layout_height="match_parent" />
stub = (ViewStub) findViewById(R.id.stub_content);
stub.setLayoutResource(R.layout.content_layout);
stub.inflate();

Categories

Resources