I'm creating an application similar to the link given here, where it shows three images transisition from one state to another when click.
1) Stage 1: When a button is clicked from another activity it enters a new activity which shows a listview of video files stored in a video directory.
2) Stage 2: When a video file is being click it does not immediately play the video instead it shows a dialog box showing the detail of the file.
3) Stage 3: The user could either Exit, select play video or show roadmap details...
Could someone help me i'm kinna new in android/java here, i'm totally lost on how to start creating the above views like how do i populate the Listview with existing video files found in my video directory?
without a specific question on how to go about implementing a certain part of a view (** just saw you asked about how to populate the list view with existing videos **), i'd point you to the great view tutorials in the android documentation. there is plenty of source and xml to get you going. it will get you going on how to implement certain views in android. and the way android uses xml to create layouts makes it very easy to nest views in a hierarchical structure.
http://developer.android.com/resources/tutorials/views/index.html
But the link you provide is all hard coding to populate the listview??
The view i wanted http://www.google.com.sg/imglanding?q=autoguard+blackbox&um=1&hl=en&sa=N&rls=com.microsoft:en-us:IE-SearchBox&rlz=1I7ADFA_en&tbm=isch&tbnid=CQTLl4767M6hpM:&imgrefurl=http://droidmill.com/autoguard-pro-124459.html&imgurl=http://cdn1.droidmill.com/media/market-media/com.hovans.autoguard.key_1.png&w=480&h=854&ei=AcHATbz7BMPorAe7v-njAw&zoom=1&iact=hc&page=1&tbnh=175&tbnw=98&start=0&ved=1t:429,r:8,s:0&biw=1366&bih=653
Maybe someone else knows, but im not sure that "popup" is a standard view. The other two views can be done easily
From something awesome
http://developer.android.com/guide/topics/ui/dialogs.html
Once you create your listview you can setOnClickListener on each cell to have it launch the dialog you create.
From something awesome
Oh well i'm stuck with the listview then... Not know exactly how to populate the dynamic video onto the listview?
Whats wrong with a listview?
Might i suggest starting with small achievable goals like:
1. Create a listview populated with something trivial, like some strings.
2. Make it so when you click the items a toast appears on screen.
3. Now make it so when they are clicked, instead of a toast, an alertdialog appears. One with the three buttons you want in it.
4. Implement the buttons so that one takes you to view the item that you clicked on. Maybe goto another activity that just displays the string fullscreen.
5. Lastly change the strings to videos and make each step work as it should.
This way if you have any bugs or questions they can be targeted towards the specific step you are on
From something awesome
So far i have search online i found this link here http://www.helloandroid.com/tutorials/musicdroid-audio-player-part-i but its a tutorial based on music files is there any relevance in this link that i could extract in here that could populate my listview with video file instead of music file?
This is what i have tried so far but i'm kinna stuck not knowing how to continue anymore?? Can someone help...
Code:
public class ListViewActivity extends ListActivity {
private List<String> Videos = new ArrayList<String>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.videolistview);
updateVideoList();
}
public void updateVideoList()
{
File VideoList = new File(ServiceRecording.TempFile.getPath() + "");
if (VideoList.listFiles().length > 0)
{
for (File file : VideoList.listFiles())
{
Videos.add(file.getName());
}
setListAdapter(new ArrayAdapter<String>(this, R.layout.video_items));
}
}
}
Hi i have done little bit of modification to my above codes but or rather now i'm faced with how am i going to change the feel and look similar to the one in softwarepassion using OrderAdapter with link here
http://www.softwarepassion.com/android-series-custom-listview-items-and-adapters/comment-page-4/#comment-1509 but i have no idea how to implement the above into my codes but at the same time it complement with the "dynamic" nature of video list rather than in the context it only fits two file object in shown in the link...
Can someone help me please..
Code:
public class ListViewActivity extends ListActivity {
private List<String> videoItems = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.videolistview);
getVideoFiles(new File("/sdcard/Video_List").listFiles());
}
public void getVideoFiles(File[] videoList)
{
videoItems = new ArrayList<String>();
for (File file : videoList)
{
videoItems.add(file.getName());
}
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, videoItems));
}
}
Related
Hey all,
I'm a new Droid developer (but long time Java programmer) and have been playing around with writing some apps. I've managed to get my first app working really well but have hit a snag. The program, which lets me view recent PVP comics, works like this:
1. Download the RSS from PVP
2. Parse the RSS to pull out comic links
3. Show the most recent comic (download it if needed) and allow user to view previous comics
Everything works fine. However, there is one thing that I just can't seem to figure out how to stop. The download of the RSS and image files take place in threads. In order to get the RSS immediately on load I put my method call in the onCreate() method. This works great. However, every time I rotate the phone, it seems like everything resets itself and reloads the RSS again.
I tried using a global boolean variable "first" which gets set to false when I first load the RSS, but when the phone is rotated it goes back to true. I'm obviously missing something in terms of how applications work on the android, but have been unable to find any work-arounds.
Any suggestions for me? I'm at a loss.
Thanks for any help.
Matthew
PS. Here's the basic structure of the code:
Code:
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// set up all the appropriate listeners and layout stuff
loadRSS(); // this is the method that I only want to call the first time
}
I tried the following with no luck:
Code:
private boolean first = true;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// set up all the appropriate listeners and layout stuff
if (first)
{
first = false;
loadRSS(); // this is the method that I only want to call the first time
}
}
onCreate() is fired everytime the activity is loaded. If you rotate the phone you are basically reloading the activity. Put a breakpoint on the onCreate() method and you should see it get called when you rotate.
Thanks, I had seen that with a breakpoint. Is there any solution or best practice to get around it? Downloading and parsing the RSS file is a fairly expensive process (a few seconds) and I'd rather not do it except when needed (I can't cache the RSS file like I do the images as it will change over time). However, I don't want to have to click a "get it now" button on starting the app but would rather the program know to do this the first time it loads and then not again. Is there anything that allows you to either store some value in a variable that isn't reset on the "onCreate()" method or some other method that the first call should be put in (e.g. "onStartup()"...completely made that name up).
Thanks,
Matthew
I'm new to this as well, but this seems like something that you should use this Class for:
http://developer.android.com/reference/android/os/AsyncTask.html
I think you are not considering the Activity lifecycle. I don't see a problem to call LoadRSS() each time onCreate is called (probably onResume() is a better place), because LoadRSS() should spawn a thread to retrieve the RSS. If the Activity is destroyed by Android you want to keep the Thread handle to continue running the loading, you can do that saving it with onRetainNonConfigurationInstance() and restore the thread handle calling getLastNonConfigurationInstance() when the Activity is resumed, remember it could be another instance of the activity.
Code:
private Thread _rssThread;
public void OnCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// set up all the appropriate listeners and layout stuff
LoadRSS();
}
private void LoadRSS() {
_rssThread = (Thread)getLastNonConfigurationInstance();
if (_rssThread == null) {
_rssThread = new Thread(... )
}
}
public Object onRetainNonConfigurationInstance() {
return _rssThread ;
}
Probably you want to do something similar with the actual RSS already loaded, and put some logic in the Thread to update the RSS instead to reload all.
I like the suggestion of basically caching the RSS and loading from there. the Activity should basically check if it has already downloaded the RSS and just 'reload' it locally instead of downloading it again.
Failing that, why don't you just force landscape mode only since this is a comic anyway?
Unconn
What you need to do is handle configuration changes within your activity.
First, update your activity tag in the AndroidManifest.xml like so:
Code:
<activity android:name=".MyActivity"
android:configChanges="keyboardHidden|orientation">
...
</activity>
That's all you need to do to prevent your activity from being recreated with each configuration change.
If you need to update something, such as reloading the layout for an orientation change, just override the onConfigurationChanged method like so:
Code:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.myactivity);
...
}
Randroid. said:
What you need to do is handle configuration changes within your activity.
First, update your activity tag in the AndroidManifest.xml like so:
Code:
...
That's all you need to do to prevent your activity from being recreated with each configuration change.
If you need to update something, such as reloading the layout for an orientation change, just override the onConfigurationChanged method like so:
Code:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.myactivity);
...
}
Click to expand...
Click to collapse
this is correct
That worked perfectly! Thanks a lot for the help.
Dear XDA,
I am a noob developer and I am trying to create my first real android application. (outside of Hello World prompts and predetermined tutorial programs) I am looking for a bit of guidance on how to best approach my project idea. What I want to do is create a sort of personal cook book for a friend with a main menu with options that takes you to a submenu with additional options that will take you to content pages that have return home buttons.
Please keep in mind that I am still in the learning process and want to learn. Any tips, comments, or approaches would help me a lot.
I am using eclipse to program currently and heavily relying on resources like http://developer.android.com to do even the simplest things.
Thank you!
~obewah
Well without getting into much detail i would say that you would need to come up with a data structure to store your recipes in, make some layouts for the screens you want to display. Also try to reuse the Activity that displays the recipe. When you start that Activity you can send an Extra in the Intent to specify which recipe to display. This will make it very easy to add recipes on the fly
From something awesome
Additional to what killersnowman said, I would recommend you to study ListActivity, and also databases, so you can add recipes from app.
Also you may want take a look to shared preferences.
If you have some coding question, feel free to contact me
Cheers From Colombia
D4.
Depends on if you want to be able to add/edit recipes or not. If you're going to add/edit etc., you'll want to do a database. If you just want to display recipes, reading in flat files would probably be easiest.
Probable be best to use strings.XML for the recipes. And for the buttons search for information about onClickListener and intent.
lukemovement1 said:
Probable be best to use strings.XML for the recipes. And for the buttons search for information about onClickListener and intent.
Click to expand...
Click to collapse
This might be the easiest so do this.
Sent from my SGH-T959 using XDA App
lukemovement1 said:
Probable be best to use strings.XML for the recipes. And for the buttons search for information about onClickListener and intent.
Click to expand...
Click to collapse
Easiest but not the most flexible
From something awesome
Thanks! Progress Update #1
First off thank you for all of the help so far! So far I have two XML layouts (one for the intro page with a picture, dedication, and button to the main.xml and the main with buttons to different categories inside the application)
This is my first independent code (which I am oh so proud of even if it only clicks through to another XML screen-- you have no idea how long it took me to make it work correctly)
Code:
package com.android.obewah.baristame;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class BaristaMeActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.startup);
final Button button = (Button) findViewById(R.id.startupBU);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click {
setContentView(R.layout.main);};}
);}}
I am still trying to wrap my brain around how I am going to put in the recipes.
My current plan of action is to create a scroll menu that pops up when you select a category (via button on main page) that leads you to an XML of the recipe.
However this seems like it may be an unnecessarily difficult approach. I don't plan to have an option of adding recipes from the app just for it to be a reference.
Thoughts/Comments?
~obewah
final Button button = (Button) findViewById(R.id.startupBU);
Click to expand...
Click to collapse
Im going to change this too-
final Button startupBU = (Button) findViewById(R.id.startupBU);
to keep things ID'ed correctly
obewah said:
First off thank you for all of the help so far! So far I have two XML layouts (one for the intro page with a picture, dedication, and button to the main.xml and the main with buttons to different categories inside the application)
This is my first independent code (which I am oh so proud of even if it only clicks through to another XML screen-- you have no idea how long it took me to make it work correctly)
Code:
package com.android.obewah.baristame;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class BaristaMeActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.startup);
final Button button = (Button) findViewById(R.id.startupBU);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click {
setContentView(R.layout.main);};}
);}}
I am still trying to wrap my brain around how I am going to put in the recipes.
My current plan of action is to create a scroll menu that pops up when you select a category (via button on main page) that leads you to an XML of the recipe.
However this seems like it may be an unnecessarily difficult approach. I don't plan to have an option of adding recipes from the app just for it to be a reference.
Thoughts/Comments?
~obewah
Click to expand...
Click to collapse
Might i suggest not just changing the layout in the onClickListener but calling startActivity and changing to an Activity that has that layout. This will preserve the back buttons functionality without a bunch of overriding it.
From something awesome
killersnowman said:
Might i suggest not just changing the layout in the onClickListener but calling startActivity and changing to an Activity that has that layout. This will preserve the back buttons functionality without a bunch of overriding it.
Click to expand...
Click to collapse
Please elaborate on how I would do that (and forgive my ignorance)
~obewah
this might interest you
http://developer.android.com/guide/practices/design/seamlessness.html#multiple-activities
Don't Overload a Single Activity Screen
Any application worth using will probably have several different screens. When designing the screens of your UI, be sure to make use of multiple Activity object instances.
Depending on your development background, you may interpret an Activity as similar to something like a Java Applet, in that it is the entry point for your application. However, that's not quite accurate: where an Applet subclass is the single entry point for a Java Applet, an Activity should be thought of as one of potentially several entry points to your application. The only difference between your "main" Activity and any others you might have is that the "main" one just happens to be the only one that expressed an interest in the "android.intent.action.MAIN" action in your AndroidManifest..xml file.
So, when designing your application, think of your application as a federation of Activity objects. This will make your code a lot more maintainable in the long run, and as a nice side effect also plays nicely with Android's application history and "backstack" model.
do you know any html coding? because you can use a webview to load a .html file from R.raw.file.html. i have done this with my change log on my app. also if you using strings.xml have a look at using the \n to add a new link.
Update 3
Well the first two buttons took me about two hours each. Then the next 8 or so took 15 min.
Here is what the code looks like atm; can anyone tell me how to make the back button cause it to go back one step in the program and not exit?
Code:
package com.android.obewah.baristame;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.Window;
import android.widget.Button;
public class BaristaMeActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.startup);
Button startupBU = (Button) findViewById(R.id.startupBU);
startupBU.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Perform action on click
setContentView(R.layout.main);
//start rec. buttons
}
});}
Class mystuff;
public void toreci(View v) {
setContentView(R.layout.make);
}
public void toramer(View v) {
setContentView(R.layout.ramer);
}
public void tohome(View v) {
setContentView(R.layout.main);
}
public void torcapp(View v) {
setContentView(R.layout.rcapp);
}
public void torlatt(View v) {
setContentView(R.layout.rlatt);
}
public void torbrev(View v) {
setContentView(R.layout.rbrev);
}
public void tordopp(View v) {
setContentView(R.layout.rdopp);
}
public void toriame(View v) {
setContentView(R.layout.riame);
}
public void torilat(View v) {
setContentView(R.layout.rilat);
}
public void toribre(View v) {
setContentView(R.layout.ribre);
}
public void test(View v) {
setContentView(R.layout.test);
}
}
Agree with killersnowman, don't overload the activity.
Have a recipe activity and layout. Make the button start the recipe activity and pass extra's (ints, strings, booleans) across in a bundle.
Here is an example on how to do it.
http://droidapp.co.uk/?p=48
Make the recipe activity read from the bundle, and then populate textviews / images etc based on them.
eatmold said:
Agree with killersnowman, don't overload the activity.
Have a recipe activity and layout. Make the button start the recipe activity and pass extra's (ints, strings, booleans) across in a bundle.
Here is an example on how to do it.
http://droidapp.co.uk/?p=48
Make the recipe activity read from the bundle, and then populate textviews / images etc based on them.
Click to expand...
Click to collapse
Ok, I have some dumb questions for you please forgive me in advance.
1) So what you are trying to tell me is to create another .java activity file that the main activity forwards to in order to preserve the integrity of the main activity. This new activity should be activated by the click here to start button and it will have all of the button code in it:
Code:
public void tolabou(View v) {
setContentView(R.layout.lcoff);
}
public void toldrip(View v) {
setContentView(R.layout.ldrip);
}
public void tolflav(View v) {
setContentView(R.layout.lflav);
Is that right?
2) Can you give me a idiot friendly definition of "activity, ints, strings, booleans, and bundle" and how they compliment each other
3) Right now I have a layout.xml for each recipe is that bad?
Feel free to answered all or any part of those questions and again I am truly grateful for all of the help I have received!
Well i can answer #2.
For more on activities: http://developer.android.com/reference/android/app/Activity.html
An activity is like each "part" of a program. You can have as any as you want. The main one gets called by the launcher to start the app.
For variable types look at: http://download.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
Int = number without decimal (-7,0,1,8) -2,147,483,647 to 2,147,483,647 max.
for decimals use float or double
string = text. ("Hello World!")
boolean = true/false (1/0, on/off, whatever).
bundle = some android thing. I believe it can save the state of your program to resume and stuff.
For future referance:
Java Tutorials: http://download.oracle.com/javase/tutorial/index.html (Lots of good stuff for starting programming and java)
Android Dev: http://developer.android.com/guide/index.html (Android specific stuff)
OK, I'll try to explain the process:
Main Screen:
1 Activity : main.java (This is the Java class, contain java code)
1 Layout : main.xml (This is the XML layout, linked to the class in setContentView)
Recipe Screen:
1 Activity : recipe.java
1 Layout : recipe.xml
So if in the main screen there are 2 buttons ("Lasagne" and "Pasta Bake"). Pressing either of these buttons will launch the recipe screen, but will pass a different string in the bundle to the new activity:
Code:
LasagneButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Intent myintent = new Intent("com.whatever.whateverapp.RECIPE");
Bundle mybundle = new Bundle();
mybundle.putString("recipename", "lasagne");
myintent.putExtras(mybundle);
startActivity(myintent);
}
});
The code above is creating a new intent, and a bundle. Adding a string called "recipename" to the bundle and setting it's value to "lasagne". This bundle is then added to the intent, and the activity is started. For the second button you would do exactly the same but set the string to "PastaBake".
So now when the recipe activity starts you need to extract the string, the next code should be placed under onCreate in your recipe activity:
Code:
Bundle mybundle = getIntent().getExtras();
String recipename = mybundle.getString("recipename");
Now with this recipename string you will need to populate your layout.
Hope that makes it a bit clearer. Here are some short tutorials I have written that may help you understand the basics a bit more (BTW: I am no expert, and have only been programming Android / Java for 6 months or so):
Buttons & Actions: http://droidapp.co.uk/?p=4
Changing Screens: http://droidapp.co.uk/?p=24
You will need to read and understand the second one to understand setting up activities as they need to be declared in the AndroidManifest file.
I just discovered how to use the action bar to have a OptionsMenu. I just solved a problem with it and I wanted to know if I did it the right way.
What I did
So, I added the menu to a fragment started by an activity, adding to it the setHasOptionsMenu(true) in the onCreate method and setting up the two convenience methods public void onCreateOptionsMenu() and public boolean onOptionsItemSelected() of course setting up the xml first.
The problem
Now, if I rotate my device in landscape mode the button in the action bar duplicates. If I put it in portrait mode again, the number of items stays the same (I'm sure it doesn't actually increase, checked the size in different ways) though.
What I thought and how I solved it
So, I was thinking about some fragment overlaps, but if they actually overlap then I shouldn't notice anything, right?
Is the menu being recreated, while not destroyed when the fragment is destroyed?
I solved the problem removing the item in the menu, in the Fragment.onDestroy() method manually.
Is the menu supposed to be cleared manually, or there is something wrong with my code (eg. fragments overlapping, etc..) ?
domenicop said:
Is the menu supposed to be cleared manually, or there is something wrong with my code (eg. fragments overlapping, etc..) ?
Click to expand...
Click to collapse
Could you please post your code? That would make helping much easier.
nikwen said:
Could you please post your code? That would make helping much easier.
Click to expand...
Click to collapse
Of course. Thanks for the interest.
This is the onCreate method of MainActivity.java, from where I handle the arrangement of fragments on the screen.
Also, place check my comment under the line "Log.d(TAG, "Orientation Portrait detected.");", where I try to explain why I handle fragments in that specific way. It's the way I understood it, but I'm not sure if that's correct.
Code:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Initialize the mDatabase
mContactsDatabase = ContactsDatabase.getInstance(getApplicationContext());
// Determine device orientation
mDualPane = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
// Set the fragment that will be changed
mFragmentToReplace = mDualPane ? R.id.contactsPagerFragmentContainer : R.id.portraitFragmentContainer;
// Set up the GUI
FragmentManager fm = getSupportFragmentManager();
if (!mDualPane) {
Log.d(TAG, "Orientation Portrait detected.");
// First, look for previously saved fragments
// findByFragmentId(int id) look for the fragment that was previously associated
// to the resource that has for id the argument passed in. Then, we try to cast it
// to the type of fragment we want, and if that goes all right, we have our fragment.
// Else, null will be returned.
mContactListFragment = (ContactListFragment) fm.findFragmentById(R.id.portraitFragmentContainer);
if (mContactListFragment == null) {
mContactListFragment = ContactListFragment.newInstance(mContactsDatabase);
fm.beginTransaction()
.replace(R.id.portraitFragmentContainer, mContactListFragment)
.commit();
}
}
else {
Log.d(TAG, "Orientation Landscape detected.");
// First, look for previously saved fragments
mContactListFragment = (ContactListFragment) fm.findFragmentById(R.id.landscapeFragmentContainer);
mContactsPagerFragment = (ContactsPagerFragment) fm.findFragmentById(R.id.contactsPagerFragmentContainer);
if (mContactListFragment == null) {
mContactListFragment = ContactListFragment.newInstance(mContactsDatabase);
fm.beginTransaction()
.replace(R.id.contactListFragmentContainer, mContactListFragment)
.commit();
}
if (mContactsPagerFragment == null) {
final int FIRST_CONTACT_POSITION = 0;
mContactListFragment = ContactListFragment.newInstance(mContactsDatabase);
mContactsPagerFragment =
ContactsPagerFragment.newInstance(FIRST_CONTACT_POSITION, mContactsDatabase);
fm.beginTransaction()
.replace(R.id.contactsPagerFragmentContainer, mContactsPagerFragment)
.commit();
}
}
}
This are the relevant pieces of the ContactListFragment.java, that have something to do with the menu
Note that I changed the way I checked for double menu entries.
Now I check if (menu.size() != 1), because I have just one item in there.
If I remove that clause, there will be two item in the menu after rotating to landscape mode, and if I take the device back to portrait mode, the two items will remain two. That's so even if I change from landscape to portrait and vice versa a hundred times from now, the menu items will always be two.
Code:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
Bundle args = getArguments();
mDatabase = (ContactsDatabase) args.getSerializable(DATABASE);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
if (menu.size() != 1) {
inflater.inflate(R.menu.contact_list_fragment_menu, menu);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.addContactMenu:
mCallback.onAddContactMenuOptionSelected();
default:
return super.onOptionsItemSelected(item);
}
}
domenicop said:
I just discovered how to use the action bar to have a OptionsMenu. I just solved a problem with it and I wanted to know if I did it the right way.
What I did
So, I added the menu to a fragment started by an activity, adding to it the setHasOptionsMenu(true) in the onCreate method and setting up the two convenience methods public void onCreateOptionsMenu() and public boolean onOptionsItemSelected() of course setting up the xml first.
The problem
Now, if I rotate my device in landscape mode the button in the action bar duplicates. If I put it in portrait mode again, the number of items stays the same (I'm sure it doesn't actually increase, checked the size in different ways) though.
What I thought and how I solved it
So, I was thinking about some fragment overlaps, but if they actually overlap then I shouldn't notice anything, right?
Is the menu being recreated, while not destroyed when the fragment is destroyed?
I solved the problem removing the item in the menu, in the Fragment.onDestroy() method manually.
Is the menu supposed to be cleared manually, or there is something wrong with my code (eg. fragments overlapping, etc..) ?
Click to expand...
Click to collapse
I agree with nikwen but broadly the idea is...
- the menu belongs to the Activity not the Fragment.
- for an Activity for which you'd like an options menu you override onCreateOptionsMenu and do 2 things...
1/ call menu.add(...) for each menu item
2/ return 'true' at the end, so that your menu can be displayed
Also, see the Activity docs for onCreateOptionsMenu()
"This is only called once, the first time the options menu is displayed.
To update the menu every time it is displayed, see onPrepareOptionsMenu(Menu)."
If you want to add menu options to the Activity menu from within a Fragment you can also..
- override setHasOptionsMenu() in Fragment to return true
- override onCreateOptionsMenu() to add any items you like (just like you did at the Activity level)
- override onDestroyOptionsMenu()
The key thing here is that onCreateOptionsMenu() in Fragment is adding to the Activity menu.
It's hard to see without debugging exactly what's going on here but watch for calls to all of the above methods in Activity and Fragment and that will probably tell you what's going on.
If it is possible to control all menu options at the Activity level instead of the Fragment level, I would do that.
If not, and you need to use the Fragment menu methods, beware of Android's Fragment management (saving / restoring state)
Also, make sure your Fragments have an ID and/or tag.
(from the docs..)
"The fragment being instantiated must have some kind of unique identifier so that it can be re-associated with a previous instance if the parent activity needs to be destroyed and recreated. This can be provided these ways:
If nothing is explicitly supplied, the view ID of the container will be used.
android:tag can be used in <fragment> to provide a specific tag name for the fragment.
android:id can be used in <fragment> to provide a specific identifier for the fragment."
Finally, if all else fails, using Menu's findItem() before calling add() would be a safeguard, I suppose.
---------- Post added at 10:14 PM ---------- Previous post was at 09:52 PM ----------
domenicop said:
Of course. Thanks for the interest.
Click to expand...
Click to collapse
Sorry caught in the crossfire - have only just seen your code.
I think much of the above applies.
Set the menu up in the Activity instead of the Fragment, if you can.
I would also consider using layout-port and layout-land to control your two different layouts.
PicomatStudios said:
I agree with nikwen but broadly the idea is...
- the menu belongs to the Activity not the Fragment.
- for an Activity for which you'd like an options menu you override onCreateOptionsMenu and do 2 things...
1/ call menu.add(...) for each menu item
2/ return 'true' at the end, so that your menu can be displayed
Also, see the Activity docs for onCreateOptionsMenu()
"This is only called once, the first time the options menu is displayed.
To update the menu every time it is displayed, see onPrepareOptionsMenu(Menu)."
If you want to add menu options to the Activity menu from within a Fragment you can also..
- override setHasOptionsMenu() in Fragment to return true
- override onCreateOptionsMenu() to add any items you like (just like you did at the Activity level)
- override onDestroyOptionsMenu()
The key thing here is that onCreateOptionsMenu() in Fragment is adding to the Activity menu.
It's hard to see without debugging exactly what's going on here but watch for calls to all of the above methods in Activity and Fragment and that will probably tell you what's going on.
If it is possible to control all menu options at the Activity level instead of the Fragment level, I would do that.
If not, and you need to use the Fragment menu methods, beware of Android's Fragment management (saving / restoring state)
Also, make sure your Fragments have an ID and/or tag.
(from the docs..)
"The fragment being instantiated must have some kind of unique identifier so that it can be re-associated with a previous instance if the parent activity needs to be destroyed and recreated. This can be provided these ways:
If nothing is explicitly supplied, the view ID of the container will be used.
android:tag can be used in <fragment> to provide a specific tag name for the fragment.
android:id can be used in <fragment> to provide a specific identifier for the fragment."
Finally, if all else fails, using Menu's findItem() before calling add() would be a safeguard, I suppose.
---------- Post added at 10:14 PM ---------- Previous post was at 09:52 PM ----------
Sorry caught in the crossfire - have only just seen your code.
I think much of the above applies.
Set the menu up in the Activity instead of the Fragment, if you can.
I would also consider using layout-port and layout-land to control your two different layouts.
Click to expand...
Click to collapse
Wow. thanks for that detailed answer. :good: (Why have I used all my thanks?)
I've always put it into the Activity as well but it might make sense to add it to the Fragment sometimes. For example if you need the same Fragment in multiple Activities...
In that case you'd need to add a listener to the item in the Fragment method though.
@PicomatStudio Thank you for the detailed answer, I really appreciate that =)
Now I'm creating the menu in the activity and I don't have to worry about the fragments life cycle anymore.
The only problem is: I didn't get the menuInflater for free here, I guess it's because of the fact that in the Fragment scenario, I had to use the Activity inflater, whereas here in the activity, I can get my own, with getMenuInflater().
Here's the way I modified it, now is in MainActivity.java.
Please report back if you find something strange
Code:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (getSupportFragmentManager().findFragmentByTag(CONTACT_LIST_FRAGMENT) != null)
getMenuInflater().inflate(R.menu.contact_list_fragment_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.addContactMenu:
onAddContactMenuOptionSelected();
default:
return super.onOptionsItemSelected(item);
}
}
domenicop said:
@PicomatStudio Thank you for the detailed answer, I really appreciate that =)
Now I'm creating the menu in the activity and I don't have to worry about the fragments life cycle anymore.
The only problem is: I didn't get the menuInflater for free here, I guess it's because of the fact that in the Fragment scenario, I had to use the Activity inflater, whereas here in the activity, I can get my own, with getMenuInflater().
Here's the way I modified it, now is in MainActivity.java.
Please report back if you find something strange
Code:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (getSupportFragmentManager().findFragmentByTag(CONTACT_LIST_FRAGMENT) != null)
getMenuInflater().inflate(R.menu.contact_list_fragment_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.addContactMenu:
onAddContactMenuOptionSelected();
default:
return super.onOptionsItemSelected(item);
}
}
Click to expand...
Click to collapse
I don't tend to use MenuInflater (just menu.add()..)
But looking at the docs it takes a Context so could you do..
Code:
new MenuInflater(this);
.. from your Activity ?
On a general design point the less your Activity depends on its Fragments the better, I reckon.
domenicop said:
The only problem is: I didn't get the menuInflater for free here, I guess it's because of the fact that in the Fragment scenario, I had to use the Activity inflater, whereas here in the activity, I can get my own, with getMenuInflater().
Click to expand...
Click to collapse
Well, you can get one:
Code:
getActivity().getMenuInflater();
I've been trying to learn to program for Android lately by simply coming up with ideas and implementing them. It started out easy enough with pulling information from an online RSS feed and showing this in a nice environment. But the current idea has me stumped.
I'd like the following to happen:
Take a picture using intent
Entire picture is shown in a new activity
Zoom in on a certain spot
Add predefined items to the picture
Press next which connects the items from left to right
Add some more items
Press next to connect the new items
Zoom out
Save the image
First taking a picture, this wasn't too hard using the camera intent:
Code:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
I can then extract the absolute path from fileUri with the following line:
Code:
String path = new File(fileUri.getPath()).getAbsolutePath();
This path can be put in a bundle which can be put in an intent which is then used to start the activity that should show the image.
Code:
public class TestActivity extends Activity implements SurfaceHolder.Callback {
private static final String TAG = TestActivity.class.getSimpleName();
private String path = "";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SurfaceView view = new SurfaceView(this);
setContentView(view);
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
path = bundle.getString("path");
view.getHolder().addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas canvas = holder.lockCanvas();
if (canvas == null) {
Log.d(TAG,"Can't draw because canvas is null");
}
else {
Bitmap bitmap = BitmapFactory.decodeFile(path);
Paint paint = new Paint();
if(bitmap == null) {
Log.d(TAG,"Can't draw because bitmap is null");
}
else {
canvas.drawBitmap(bitmap,0,0,paint);
}
holder.unlockCanvasAndPost(canvas);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int frmt, int w, int h) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
The first issue here is that it of course doesn't show the entire photo. Not that surprising considering it's larger than the view. Ideally I'd like to zoom out to show the entire photograph. Once I've zoomed one way I'd assume that zooming in on the part that you want should also be possible.
Next is adding the objects. My idea was simply catching any touch events and adding a new object once the finger is released. This way I'd end up with a list of items with each having a draw function which can be called through the surfaceview when it is redrawn.
Connecting these items could simply be done by creating a line object and going through the list of all items and using their locations for the begin and endpoints of the lines
One of the big issues here is that the x and y locations would be relative to the screen, not to the photo. Which would mean that when you zoom back out the entire background would change but the actual items would remain at the same spot and in the same size.
I've been searching and searching for any tutorial or other question about the same issue, but either I've had no luck or I've been using the wrong keywords. And for all I know everything I have up till now could be wrong.
If anyone could give some pointers, or maybe knows a guide or tutorial somewhere or some better keywords I could use for searching I'd really appreciate it.
Xylon- said:
One of the big issues here is that the x and y locations would be relative to the screen, not to the photo. Which would mean that when you zoom back out the entire background would change but the actual items would remain at the same spot and in the same size.
Click to expand...
Click to collapse
would you just not need to either control or track the sample/scale if the image so that you know the 1st pixel displayed (top left) and the scale factor, then the eventX/Y can be processed to be relative to what you want ?
Basicly I have very same code as described here http://www.learn2crack.com/2013/12/android-swipe-view-tab-layout-example.html:
In each of the fragments I have different asynctask, that just fetches data from website. Fragment class looks like this :
Code:
TextView text;
String content;
View today;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
today = inflater.inflate(R.layout.today, container, false);
text = (TextView) today.findViewById(R.id.textView);
// ((TextView) today.findViewById(R.id.textView)).setText("Today");
new RetriveSiteData().execute("http://menza.lupajz.eu/?den=dnes");
content = (String) text.getText();
return today;
<here is the asynctask, too long >
}
I am wondering if the data is always fetched, while swiping through fragments if the TabPagerAdapter class (on the website) has this method implemented the same way
Code:
@Override
public Fragment getItem(int i) {
switch (i) {
case 0:
//Fragement for Android Tab
return new Android();
case 1:
//Fragment for Ios Tab
return new Ios();
case 2:
//Fragment for Windows Tab
return new Windows();
}
return null;
}
In case if the data is always fetched and the asynctask is always executed how can I prevent that ? Maybe adding some onResume() methods to each fragment ?
What is the best solution just to make connection to website, fetch data once and then just keep displaying them while I am swiping between fragments ?
lupajz said:
Basicly I have very same code as described here http://www.learn2crack.com/2013/12/android-swipe-view-tab-layout-example.html:
In each of the fragments I have different asynctask, that just fetches data from website. Fragment class looks like this :
Code:
TextView text;
String content;
View today;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
today = inflater.inflate(R.layout.today, container, false);
text = (TextView) today.findViewById(R.id.textView);
// ((TextView) today.findViewById(R.id.textView)).setText("Today");
new RetriveSiteData().execute("http://menza.lupajz.eu/?den=dnes");
content = (String) text.getText();
return today;
}
I am wondering if the data is always fetched, while swiping through fragments if the TabPagerAdapter class (on the website) has this method implemented the same way
Code:
@Override
public Fragment getItem(int i) {
switch (i) {
case 0:
//Fragement for Android Tab
return new Android();
case 1:
//Fragment for Ios Tab
return new Ios();
case 2:
//Fragment for Windows Tab
return new Windows();
}
return null;
}
In case if the data is always fetched and the asynctask is always executed how can I prevent that ? Maybe adding some onResume() methods to each fragment ?
What is the best solution just to make connection to website, fetch data once and then just keep displaying them while I am swiping between fragments ?
Click to expand...
Click to collapse
Yes, that data is always fetched since onCreateView is always called when a Fragment which hasn't been in layout appears, whether it was already instantiated or not. Have a look at the diagram on the right here for better understanding on how the specific methods are called. The dumb solution would be to put that code into the constructor, but Google suggests not doing anything there and instead using onCreate, which is also only called once.
Instead it might be better to just fire up the tasks for each Fragment (maybe sequentially as well) in the Activity, but that depends on how much data you are loading here, since the user might be switched to the page you are loading at the very end.
Thanks for answear yea I was looking at the fragment google site and I guessed that was the problem, but I am not getting the second part.
Instead it might be better to just fire up the tasks for each Fragment (maybe sequentially as well) in the Activity, but that depends on how much data you are loading here, since the user might be switched to the page you are loading at the very end.
Click to expand...
Click to collapse
I am just getting about 30+ lines of pure text, so it is not that big.
lupajz said:
Thanks for answear yea I was looking at the fragment google site and I guessed that was the problem, but I am not getting the second part.
I am just getting about 30+ lines of pure text, so it is not that big.
Click to expand...
Click to collapse
What I meant was that if you need to load much data over a possibly slow connection and do it in a specific order (meaning start with one category, then when that's finished the next one and so on) it might be that the user is swiping to the last category that will load and has to wait untill all other have been loaded. This is what speaks against loading everything in the activity and then reloading the Fragments with their specific content, but of course this is not the case with just a few lines of text . That would be the the way I would do it (load everything in the onCreate() of the activity and pass it to the Fragments) if there is little to medium data to load since you don't have to open an internet connection everytime the user swipes thus swiping will be much smoother (or it won't show a ProgressBar like that stupid xda-app ).
If it is data that you don't need to reload more than once every day, you can think about cashing it as well!