I want to upgrade a couple of my Android apps to use Fragments. Here is a basic situation:
I have an Activity and a ListActivity. I want to convert these using fragments using the compatibility packaging. Below is what I have in the onCreate method in the Activity. (The ListActivity has similar items so I am only using the Activity as the example ere in the conversion).
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
setContentView(R.layout.rate);
Item = getIntent().getExtras().getString("name");
Category = getIntent().getExtras().getString("category");
title = (TextView) findViewById(R.id.tvRateItem);
ratingsBar = (RatingBar) findViewById(R.id.theRatingBar);
title.setText(Item);
// Display list of reviews
new starTotalTask().execute();
new starRatingTask().execute();
final EditText etTweetReview = (EditText) findViewById(R.id.etTweetReview);
Button button = (Button) findViewById(R.id.theRatingBarButton);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// do stuff
}
}
});
Button BReviews = (Button) findViewById(R.id.bReviews);
BReviews.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// do stuff
}
});
}
So you see, I have a couple of Buttons, a couple of AsyncTasks, some getIntents that are grabbing data from other Activities, some "widget" declarations referencing to the XML.
I have the basic framework already setup with a FragmentActivity (from compatibility v4 package) with a couple of fragments it points to. In fact, I have a ViewPager, and tabs set up. The correct layouts are already setup as it should be to the new Fragment view. I just don't get how to move the data as seen above. I also understand the onCreateView is where you set the layout. Outside of that, where does everything else go? Not looking for code example as much as direction -- IF POSSIBLE.
Edit: My layout is based on this: http://thepseudocoder.wordpress.com/2011/10/13/android-tabs-viewpager-swipe-able-tabs-ftw/
especially interest in:
- Where do the RatingsBar and TextView (and other xml references) go?
- what about AsyncTask?
- and how do you handle passing around data in intents?
Almost everything will be identical. The key differences are:
You need to extend FragmentActivity in place of Activity.
You need to call getSupportFragmentManager() instead of getFragmentManager().
You need to call getSupportLoaderManager() instead of getLoaderManager().
The compatibility library does not support a ListFragmentActivity (or whatever). You'll need to use a FragmentActivity instead and set up the ListView in your code.
Related
Here's a simple app, I'm trying to create logs in the printToLogs method.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v("Log0","test");
}
public void printToLogs(View view){
TextView menuTextView1 = findViewById(R.id.menu_item_1);
TextView menuTextView2 = findViewById(R.id.menu_item_2);
TextView menuTextView3 = findViewById(R.id.menu_item_3);
String item1 = (String) menuTextView1.getText();
String item2 = (String) menuTextView2.getText();
String item3 = (String) menuTextView3.getText();
Log.v("Log1",item1);
Log.v("Log2",item2);
Log.v("Log3",item3);
}
but logs with the tags Log1, Log2, Log3 are not shown at all in the logcat, what does show up is the Log0 in the onCreate method, but the other ones in printToLogs never show up when I search for them at all. I attempted re-installing the app and restarting logging. That didn't work.
The menu items are: Mango sorbet, Blueberry pie, Chocolate lava cake. And yes, I tried searching for them, and they are not in the logcat either.
If this is your actual code, you aren't even calling printToLogs in the onCreate method. You should be more diligent before posting something simple like this.
Barring a serious runtime environment issue, this problem should be fairly easy to solve.
It seems as if the printToLogs(View view) method is to be executed in response to the user clicking a button. If so, try including the following line in your activity_main.xml if you haven't already:
android:onClick="printToLogs"
This will bind the button on the UI with the printToLogs(View view) method.
If, on the other hand, printToLogs(View view) is intended to be a standalone method (i.e. one that should execute regardless of user input) it should not accept a View as an argument. For your purposes, its parameter list should be completely empty. In other words, the method signature should read:
public void printToLogs()
Also, it should be called within the onCreate(Bundle savedInstances) method. Add the following to the onCreate(Bundle savedInstances) method:
printToLogs();
This will initiate the execution of the method as soon as the app begins to run.
Make sure the logcat filter is set to "Verbose" when testing like so: (img is link since apparently I need 10 rep. to embed images into answers directly)
logcat filter
heyy add your method/function name in your button by using property section or just android:onClick in your xml file and then it will be solved
I am working on a practice android project, and I am trying to implement polymorphism ideas into my program. So far, I have created two different XML layouts, one for tablets, and one for phones. They both have a button, but I want the button to do different things depending on which layout it is in. I am using the onClick property, and both layout's buttons refer to the same method.
In my buttonClick method, I want to find out which layout is is currently being shown, and I am trying to do it this way,
public void buttonClick(View ve)
{
View v = getCurrentFocus();
//According to the API, this method returns the current view,
//but the Log Tag says that it is null, which should not be the case.
Log.i(TAG, "Current View is " + v.getContentDescription());
//I want to control what happens polymorphically using the next if-else
//clause,depending on the layout, I think that this part would work if
//the above code works alright.
if(v.getId() == R.id.TabletLayout)
{
TextView myText = (TextView)findViewById(R.id.textView);
if(myText.getText().toString().contains("World"))
myText.setText(R.string.ayo_android);
else
myText.setText(R.string.hello_world);
Log.i(TAG, "changing words");
}
else{
Log.i(TAG, "Creating new Activity");
myText = (TextView)findViewById(R.id.textView);
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("screenText", myText.getText().toString());
startActivity(intent);
}
}
Thanks.
That's not the way to do it. If you want them to do different things, have the refer to different click handlers. If they're widely different they shouldn't even have the same id. The entire idea behind the automatic layout overrides is that the application should never need to care which one to use.
In addition to Gabe's answer, getCurrentFocus() will not give you the layout of the activity. If you want the layout of the activity, you can use
View v = (View)findViewById(android.R.id.content);
I am having trouble grasping a certain concept in Android UI design. The book I am referring to first uses the usual technique that Java programmers use to create UIs and that is to to create containers and add UI components to them and nest them as necessary.
Now, the book introduces a new concept where the entire UI was created using an XML file. The code is pasted below:
package com.oreilly.android.intro;
import android.app.Activity;
import android.os.Bundle;
/**
* Android UI demo program
*/
public class AndroidDemo extends Activity {
private LinearLayout root;
#Override public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main);
root = (LinearLayout) findViewById(R.id.root);
}
}
so basically, I can use any of them ?
Simple answer,yes, you can use either approach. However, there are some limitations to each such as there are layout properties that must be set in xml if you want to use them. I can't think of what any are off-hand but I can look them up.
For the most part, creating the layouts is much simpler to do in xml but you do have the option of setting Views and layouts in Java if you need to such as creating an unknown number of Buttons depending on some user-defined variable.
When you create your UI in xml then you inflate it in your Java code. This is normally done in onCreate() using
setContentView(R.layout.main);
as you see in your example. But it can also be done with an inflater.
The thing to remember here is to inflate your layout, using either method, before trying to initialize any views in the layout or you will get a NPE when trying to call a method on a View defined before inflating the layout it is contained in.
A correct way
**Examples of inflating views/layouts correctly**
Button mBtn;
public class AndroidDemo extends Activity {
private LinearLayout root;
#Override public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main);
root = (LinearLayout) findViewById(R.id.root);
btn = (Button) findViewById(R.id.buttonId); // Button is initialized after inflating the layout
}
}
Incorrect way
public class AndroidDemo extends Activity {
private LinearLayout root;
#Override public void onCreate(Bundle state) {
super.onCreate(state);
Button mBtn = (Button) findViewById(R.id.buttonId); // Button is initialized before inflating layout which will return null
setContentView(R.layout.main);
root = (LinearLayout) findViewById(R.id.root);
}
}
I added the above example because I have seen a lot of people make that mistake. So don't do it...you've been warned! :)
Not entirely sure what you're asking, but the two are interchangeable.
Most of the time your UI will be done via xml. In some cases though, the ui is heavily dependent of the data, so you may need to dynamically generate it.
It basically comes down to whichever is easiest for you at the time.
Yes.
But is preferable to use xml, it is more powerful, easier and will separate layout from your code.
Take a look at the docs:
http://developer.android.com/guide/topics/ui/declaring-layout.html
How do you implement a custom view in Android so that it properly supports, or works with, the messaging queue ?
I'm trying to emulate the behavior of the built-in views so that I can properly / normally update a custom view with data within onCreate.
Currently, my custom view has ad-hoc set/update functions to put data in them. The problem with this is that my view's children views are not initialized until the first time onMeasure is called, which is after onCreate exits (which I think is how the built-ins do it).
Therefore, I want to know what the general strategy is (ie, what methods to override) to update a custom view from onCreate in such a way that the updates go into the message queue and reach the view after they are properly instantiated (just like the built-ins) ?
Thanks.
Look at View.post():
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView hello = ((TextView) findViewById(R.id.hello));
hello.post(new Runnable() {
#Override
public void run() {
hello.setText("Hello World!");
}
});
}
I'm writing a calculator application in which I would like to be able to switch between 4 modes of calculation: Decimal, Binary, Octal, and Hex. In order to manage the different UIs for the different modes, I have 4 Fragment subclasses in my Activity. Each Fragment has its own XML layout file, in addition to the main XML file for the Activity. I found a guide on the Android Developer site for inflating layouts for Fragments, and I've followed that guide. However, I would like to add listeners and so on to the various components of the layouts, preferably within the onCreateLayout method of the Fragment, or somewhere else where I could do it easily and minimize code duplication.
It appears, however, that when I try to call findViewByID to access one of the inflated Views (after I've called LayoutInflater.inflate, obviously), I get a null return value. This issue occurs whether I call findViewByID from within onCreateLayout or from elsewhere in the Activity (after the Views have, theoretically, been created). What's going wrong here?
One issue I think might be a problem is that I've overloaded the names of the Views between the various Fragment layouts. For example, the "1" button in the Binary layout has the same ID as the "1" button in the Hex layout. Is this allowed, assuming the Binary and Hex layouts are never both part of the Activity at the same time?
Thanks.
I think same id in different layout is not problem in Fragement. First you have to catch the inflated view then find whatever inside this. For example --
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.frg1, container, false);
android.util.Log.v("", "!!!!!!!!!! Frg1 !!!!!!!!!");
Button b = (Button) view.findViewById(R.id.b1);
b.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Toast.makeText(getActivity(), "here", Toast.LENGTH_SHORT).show();
}
});
return view;
}