I'm new to android development, and have set myself the task of creating a contact management application - just for the purpose of improving my skills.
The user has all the usual contact editing options available to them - find contact, new contact, edit contact, delete contact, etc. Each of these works in their own right - 'find contact' will 'select' the appropriate contact (store their ID in a public variable). If you press 'edit' or 'delete' whilst a contact is 'selected' then those functions work as they should.
But what happens when the user tries to press 'edit' or 'delete' when there is no contact selected? The simple solution would be to display the message 'please select a contact', but that is bad design. If the app needs user input, then they should be re-directed to the necessary activity to select a contact.
So when the user clicks the 'Edit' button, I wrote this very small snippet of code:
public void findContact(View view)
{
Intent intent = new Intent(this, FindContactActivity.class);
startActivityForResult(intent, 1);
}
public void editContact(View view)
{
if (Db.contact == null)
findContact(null);
else {
// navigate to edit activity
}
}
In this case, 'contact' is an object of type contact, which stores contact related information in it's own class. Db is a class that contains my database access functions - it seemed like a good spot to store a public variable that would need to be accessible from anywhere.
Now the code above obviously works fine. If a contact is selected, great - we go to the edit screen. If not, we go to the find-contact screen. But the problem is what happens once the user has selected a contact? It doesn't take them back to the edit screen again.
My ideal flow would be, in pseudo-code:
editContact()
{
if (contact is selected)
editContact();
else
{
findContact();
// once found, go to edit contact screen
editContact();
}
}
Bearing in mind I am brand new to android development, I was wondering if anyone could give me some pointers on creating the 'flow' of the application, as described above.
If I understand your problem there could be several ways to do it. I would probably simply disable the "Edit" Button if they haven't selected a contact yet because they shouldn't be able to try and edit if nothing is selected. However, if this doesn't work for you then you could pass a flag with your Intent. One thing I do sometimes is to pass a "source" flag.
After clicking edit and no contact is selected
Intent i = new Intent(Edit.this, FindContact.class);
i.putExtra("source", "edit");
startActivity(i);
then in your find contact get the extra
Intent intent = getIntent();
if ("edit".equals(intent.getStringExtra("source");
{
// create intent for EditScreen
You also could simply pass a boolean value this way with key "edit" and check if that is true. If so, then go to EditScreen if not go wherever you need to. I hope this helps. Let me know if I misunderstand.
You also will find different Intent.FLAGS very valuable
Actually android has a philosophy around the "flow" of activities which is covered here.
Since you are a new android developer it's mandatory to understand how activities are working.
By the info in your question it seems that you are not following android guidelines which is not necessarily a bad thing but you must have valid reasons not to. So by the programmatic view of your question I suggest that you disable the edit and delete buttons when a contact is not selected or if you prefer, to restrict user's choices based on the data selected or displayed.
However you are asking about the "flow" so my advice here is to study more about activities and how the back stack is working and look at the sdk examples. In most of the applications that a user can make some actions based on data selected those actions are presented to the user after a longclick on a record. In your case a pseudo flow would be something like this:
Find Activity --> Results --> Click on a Result --> Choices List (Edit, Delete e.t.c) --> Edit or Delete Activity (after edits goes back to Results)
Now about "creating a less linear flow of activities" IMO is a little too generic. You can control the flow of your activities as you want by using either the techniques in the design (look my link on top) or by code by using for example the finish method which removes the activity from the back stack.
Hope this helps...
Related
[Asking question for the first time on Stack Overflow]
I am making an application where the user will be shown with a list of locations in a recyclerView. RecyclerView has generic rows and each row has a cardview in which there is a checkbox and a textview. When the user clicks on a row, he is re-directed to a different activity where they are supposed to answer certain questions and click on save. Once clicked save, he will be re-directed to previous activity and I need that particular location's checkbox to be checked.
How can I do this?
Thanks for the help and sorry if I explained it badly.
Welcome to stack overflow. Have you read through the android documentation found here:https://developer.android.com/guide/ you are going to want to read through the activity and adapter sections of that. Also you can refer to a summarized version here https://guides.codepath.com/android/Using-an-ArrayAdapter-with-ListView#attaching-event-handlers-within-adapter
There are many ways to accomplish what you are asking. Sounds like you are looking for startActivityForResult() this method simply takes an intent and says "hey when that activity is finished I want some information back so I can do something with the result"
When you want to pass a result back to your calling activity in this case, you will need to set some data before you finish the created activity like so
Intent data = new Intent();
data.putExtra("location", selectedLocation);
setResult(RESULT_OK, data);
finish();
By doing this you can receive the result in your calling activity with the method implementation of onActivityResult(int requestCode, int resultCode, Intent data)
In your case lets say a user taps a card and you start the new activity using startActivityForResult(intent, requestCode) when the user is done with this activity and the activity is going to finish you want to set some outstate data using the Intent data passing method I showed above. Maybe you want to send the location back. Simply attach the location as an extra and receive it in your onActivityResult() implementation and then make the appropriate changes in that view based on the data. Hope that helps.
In the future, it always helps to provide example code with your question. It will help users better assist you on your issue and more importantly make users want to help you out. You seem new to android development so make sure to read through the android docs whenever you can to better your understanding of android as a whole. Cheers!
I'm creating an app where I display a list of pending challenges. When the user clicks on a challenge, he can accept it or ignore it.
Here's what I want to do and I don't know how :
if the user accepts or ignore the challenge, call this.finished and remove the challenge from the list
if the back button is pressed, do nothing, the challenge is still visible
In short, if the user really responds to the challenge I don't want it to be displayed in the list, but if he doesn't choose any option and press the back button, he didn't choses one of the two actions so I want that challenge to still be visible in the list.
I don't think it's possible to detect what button I've pressed when i go back to my main activity. I've thought about using global variables, but I don't want to misuse them either.
Just to be clear, I'm not asking how deleting a list item. But when to know deleting one depending of the actions of another activity.
Give your second activity the index you want to remove as a parameter inside the intent and let it finish by returning the index again as an intent extra (by using setresult(Intent i) and then calling finish) inside your first activity catch the result from your second activity by overwriting onActivityResult (http://developer.android.com/reference/android/app/Activity.html#onActivityResult(int, int, android.content.Intent))
see 3.3. Retrieving result data from a sub-activity in http://www.vogella.com/tutorials/AndroidIntent/article.html for a detailed howTo
Have tried searching and tested all possibilities on StackOverflow but I'm still stuck, so many apologies if this seems like a duplicate!
Here's an overview on what I'm trying to achieve:
I have a user profile. It is made up of UserProfileActivity and UserProfileFragment, where the view and data projections are handled in the fragment. A user ID (objectId) is also being passed to display the profile of the respective user.
On this user profile, you can click to a list of the user's followers (made up of ListFollowerActivity and ListFollowerFragment). On this list of followers, clicking on an individual person leads to UserProfileActivity again, this time with a different user ID.
What's happening currently:
The code I currently use to load the UserProfileActivity (with a new user ID) from the ListFollowerFragment is;
Intent intent = new Intent(parent, UserProfileActivity.class);
Bundle bundle = new Bundle();
bundle.putString(C.bundleKey.objectId, objectId); // objectId = user ID!
intent.putExtras(bundle);
startActivity(intent);
I've done a out.println on the object ID from the reload intent in ListFollowerFragment and it correctly prints the correct user ID. (The ID of the user which is tapped on.)
But in reality, the app reloads the same user profile (which is the former user ID and not the new one) again.
How do I get the UserProfileFragment to refresh the data (and the view) to reflect the correct user?
Some observations:
It seems that UserProfileActivity is simply 'restoring' from its previous state (previous user ID) from second and subsequent loads. (Any out.println() I do from onCreate() in UserProfileActivity and onCreateView() in UserProfileFragment is not readable from the second load onwards, but reads correctly on the first!)
I've also attempted finish() on UserProfileActivity when navigating to ListFollowerActivity, and all subsequent loads of UserProfileActivity worked with the correct user Ids, presumably because the activity is killed and restarted. But this also means the user is unable to back-navigate. Would really appreciate any help. Thanks! (:
I think you can get the objectID with getExtra() from your UserProfileFragment . Something like this.
if (getIntent().hasExtra("objectId"))
object_id = getIntent().getExtras().getString("objectId");
In my AndroidManifest.xml, I found the following:
<activity
android:name=".ui.UserProfileActivity"
android:theme="#style/Theme.Styled.NoActionBar"
android:launchMode="singleTask"
android:screenOrientation="portrait"/>
I changed the launchMode to 'singleTop' and all navigation began working as desired.
'standard' launch mode works too, although this will constantly create new instances of UserProfileActivity (assuming we traverse deeper into viewing profile A --> viewing A's follower list --> tap to profile B --> viewing B's follower list --> tap to profile C, I believe this is not very good for performance).
'singleTop' on the other hand, lets you reuse the current instance as long as it exists above the current activity in the stack.
I'm a very new to Java. I thought I was doing okay but have now hit a brick wall, so to speak.
The idea is I use the 'home button' '_menu' for the user to choose one of 26 formats. The format they choose has 3 variables. Those 3 variables are then used in the first xml view, along with 2 user inputs to calulate another variable. This variable is then used in a second xml view, along with a third user input here, to calculate the final answer.
I have created the 26 choices and if for example I choose option 5, on the emulator screen I see all the correct values associated with this choice. I don't think those values are getting stored anywhere. I say this because if I come out of that view and return back into it, it's not showing, as in my example, choice 5. It's showing its initial state, as though I was going into it the first time. I assume it's something to do with launching this activity from the start but is there anyway around this. Or really where do I start.
My second question is with the integer variables that I created from this choice. I need to pass them into another java file for the first set of calculations. I've tried to pass the variables/data with the, 'new intent putExtra' but can't get it to work. But I don't think I can use this anyway since the I don't want to launch the second view directly from the res/menu/ .xml view.
Not sure if this is making sense to anyone. Can someone help point me in the right direction?
I don't quite understand your first question, but it sounds like you're launching a new activity and when you quit and come back to it, everything is reset. If you're launching a new activity after selecting the options from your phone's menu button, you should implement a method that saves data to the shared preferences of the main activity. This method should be called on the activities onPause(), onDestroyed(), or onStop() method. You can also add a method on onResume() where the activity checks if there's any data stored in shared preferences and if so, make the desired changes.
As for your second question...I kinda don't understand it either. new intent and putextra is used when you're starting a new activity and want to pass data to it. Views are not "launched" they are only inflated and brought on display whenever you want. I did an app once where I had everything in one activity and just using setContentView() method all the time. In the long run, it just complicated everything. It is easier to keep things simple and launch activities. Here is an example of some variables being passed to a new activity:
On my main activity (FirstActivity) I have:
(when newActivityButton is clicked)
case R.id.newActivityButton:
Intent mIntent = new Intent(FirstActivity.this,SecondActivity.class);
String[] luckyNumbers = {
luckyNumber[0].getText().toString(),
luckyNumber[1].getText().toString(),
luckyNumber[2].getText().toString(),
luckyNumber[3].getText().toString(),
luckyNumber[4].getText().toString(),
luckyNumber[5].getText().toString()};
mIntent.putExtra("luckyNumbers", luckyNumbers);
mIntent.putExtra("message", messageField.getText().toString());
FirstActivity.this.startActivity(mIntent);
break;
luckyNumbers[] is an array of textviews.
Then on my NewActivity onCreate(), I have:
message = getIntent().getExtras().getString("message");
Log.i("TAG", message);
luckyNumbers = getIntent().getExtras().getStringArray("luckyNumbers");
cv.setLuckyNumbers(this.luckyNumbers);
cv.setMessage(this.message);
where cv is just a custom view I created with its own methods
I have a search feature with a list view. When the user click on search and filters the result the activity is loaded from the beginning. So here is the flow.
User opens my application (Gets the whole list ot items) -> Search1 (Filtered search) -> Search2 (Filtered result 2) -> Search3 (Filtered result 3). Now when the user clicks back he goes to Search 2 -> then back to result 1 -> then back to the mail list.
This is how is my application working now. I want this to change as when users is on any search result I want him to go back to main list without going back to any search results.
Basically I dont want android system to track the search results so that when user clicks back, he should directly go to the main list.
How do I do this. Please advice if you have any alternative for this. Thank you for your advice and time. Thank you.
You should set your search activity to be android:launchMode="singleTop" in your manifest, that way there's a single search activity and you're only responding to search intents within it. This is actually the "ideal" behavior according to the docs.
When you are done with the search results you could finish that activity. You might even be able to use finishOnTaskLaunch to achieve the same thing and it is probably more desirable too.