Navigation View - Support Google - android

I am doing an application where I want to put the user name in nav_header_home.xml (top) but I am not able to send the name parameter obtained at the moment the user logs in to the activity home. I am using to send:
abreInicio.putExtra("nome_usuario", dados[3]);
and to receive, in the java da home I have:
public class home extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
String nomeusuario, email;
TextView txtpontosr, txtnome;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
txtnome = (TextView) findViewById(R.id.txtnome);
txtpontosr = (TextView) findViewById(R.id.txtpontosr);
nomeusuario = getIntent().getExtras().getString("nome_usuario");
email = getIntent().getExtras().getString("email_usuario");
Also I would like to put the user's points in the same place, this is not fixed, so how can I implement a swipe refresh in activity home to update this data?
Finally I would like advice, for a better UI would be better a navigation view with activities and in those activities in the tolbar a back or a navigation view with activities that have navigation view or fragments?

In your intent, your are passing an array of String. Instead, make your String an ArrayList and accept it in your activity

Related

How can I change the title of a Fragment without changing the title of the MainActivity?

I would like that in each Fragment the title of the ActionBar will be adapted. For example, if I select the option "Lists" (that is a Fragment), the title of the ActionBar have to be "Lists".
I can do it using the following code:
getActivity().setTitle("Lists");
but when I go back to MainActivity (using the menu option or the back button on the mobile phone) it maintains the title "Lists" instead of "My application" that is the default title.
If I try to set the title on MainActivity:
setTitle("My application");
it is not changed.
How can I maintain the title of the MainActivity and modify the title in each of the Fragments?
Thanks in advance!
Finally I am able to modify the title of your MainActivity after enter in a Fragment and modify the title of the ActionBar in it. I needed to change it with two different events: when I click on the menu of the application and when I press back button of the mobile phone. I will separate my answer in two parts, one for each event:
- To change title on MainActivity when you press back button on your mobile phone
You need to use onBackPressed() method on your MainActivity.class to detect the event and then use setTitle method to change the title of your ActionBar.
#Override
public void onBackPressed() {
setTitle("Lists");
}
- To change title on MainActivity when you press option "Home" in your menu.
On your onNavigationItemSelected method you can detect when you press the option "Home" and then start a new Fragment (let's call it MainFragment) which returns an empty layout so if you are in another Fragment, for example AnotherFragment (with another ActionBar title) and you press your "Home" option in your menu you can set again the title of your MainActivity as default one in your MainFragment with the following code:
getActivity().setTitle("Lists");
In this way you will be able to change the title of your MainActivity maintaining its layout.
Try using getSupportActionBar().setTitle("title");
That's what I use and it seems to work good. Here's an example using my code where I add fragments to a viewpager.
private void addPages(ViewPager pager) {
MyFragPagerAdapter adapter = new MyFragPagerAdapter(getSupportFragmentManager());
Intent intent = getIntent();
String workout = intent.getStringExtra("work");
Bundle args = new Bundle();
args.putString("work", work);
String title = args.getString("work");
switch(title) {
case "w29w1" : {
getSupportActionBar().setTitle("Work 29 Week 1");
break;
}
case "w29w2" : {
getSupportActionBar().setTitle("Work 29 Week 2");
break;
}
MondayFragment mondayFragment = new MondayFragment();
mondayFragment.setArguments(args);
In that example, I'm simply setting the title of the toolbar to something, depending on the intent it got from the previous class, as the fragment is used for multiple sets of data.
Put this code on onResume() of both activity and Fragment
Fragment:
#Override
public void onResume() {
super.onResume();
if(getActivity().getSupportActionBar()!=null)
getActivity().getSupportActionBar().setTitle("Lists");
}
Activity:
#Override
protected void onResume() {
super.onResume();
if(getSupportActionBar()!=null)
getSupportActionBar().setTitle("Title");
}

ActionBar Back Button and Title

I have an activity that I would like the "up affordance" on.
public class ItemListActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
// ...
}
}
This adds the "back button" like I want. The problem is that the Title is not considered part of the back button in this instance. Is there any way to make it so that it behaves more like the Messaging app? In the Messaging app you can tap either the back button or the title and it will take you back to the previous activity.
Add an onClickListener to the title of your ActionBar. See this post for example: Set OnClick Listener on Action Bar Title in Android

Android Studio generated Navigation Drawer's Header

I've generated a navigation drawer using Android Studio by New -> Activity -> Navigation Drawer Activity. As a recent feature of Android Studio I didn't find enough examples through Google to access TextView in the header. I want to dynamically change the header title.
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
TextView tv = (TextView) drawer.findViewById(R.id.tvNavHeader);
In onCreate does not help me.
The NavigationView has a bug in v23.1.0. You can't access to the views contained in the HeaderView in onCreate method.
A workaround is to inflate the HeaderView and add it programatically in the onCreate method like this:
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
View header = LayoutInflater.from(this).inflate(R.layout.nav_header_view, null);
navigationView.addHeaderView(header);
TextView tv = (TextView) header.findViewById(R.id.tvNavHeader);
}
}
There is no longer need to inflate the HeaderView anymore.
View header = navigationView.getHeaderView(0);
TextView text = (TextView) header.findViewById(R.id.textView);
This works for one header. If you have several, just browse the google issue provided by Mattia.

How to set an Observer to Update Navigation Drawer after onActivityResult method's received an Intent result

In my app I want to update the Navigation Drawer with the username's nickname and email after he's logged in.
From my MainActivity I am starting a LoginActivity with the startActivityForResult(intent, PICK_ACCOUNT_REQUEST); method
to get the users registered or logged in.
After the LoginActivity returns the Intent data result (his NAME and EMAIL) back to MainActivity, the method onActivityResult() is called and there I try to update the class' global variables NAME and EMAIL with the newly received data, with no success: after every registration or log the two fields never show in the navigation drawer. Here's my code:
In the beginning of the MainActivity class I assign two variables:
String NAME = "Sign in", EMAIL = "";
These two values are inserted in my navigation drawer. After I receive the result from LoginActivity I want to update these two fields in the onActivityResult() method. This way:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
// Check which request we're responding to
if (requestCode == PICK_ACCOUNT_REQUEST) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// The user picked a contact.
String usr = data.getStringExtra("username");
String mal = data.getStringExtra("email");
this.NAME = usr;this.EMAIL=mal;
}
}
}
with no success, in fact after completion of LoginActivity I still visualize the old values within the Navigation Drawer because I'm not able to access the 2 EditText holding Username and Password from MainActivity. In fact the 2 EditText are managed inside RecyclerView.ViewHolder.
How can I set an Observer or something similar to dinamically update my Navigation Drawer's RecyclerView.Adapter?
More details below
* EDIT *
Ps. My Navigation Drawer is implemented with RecyclerView, I therefore have a RecyclerView.Adapter class and a RecyclerView.ViewHolder class inside the adapter. In MainActivity I have this code:
public class MainActivity extends ActionBarActivity{
ArrayList<DrawerItem> dataList;
RecyclerView mRecyclerView; // Declaring RecyclerView
RecyclerView.Adapter mAdapter; // Declaring Adapter For Recycler View
RecyclerView.LayoutManager mLayoutManager; // Declaring Layout Manager as a linear layout manager
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private CharSequence mTitle, mDrawerTitle;
Toolbar toolbar;
String NAME, EMAIL; int AVATARresID; //TODO update Navigation Drawer fields
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Assigning the toolbar object to the view
and setting the the Action bar to our toolbar */
toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
// enable ActionBar app icon to behave as action to toggle nav drawer
getSupportActionBar().setDisplayHomeAsUpEnabled(true); //pulsante drawer
getSupportActionBar().setHomeButtonEnabled(true); //pulsante dietro
//Initializing
mTitle = mDrawerTitle = getTitle();
AVATARresID = R.mipmap.aka;
// Add Drawer Item to dataList
dataList = new ArrayList<>();
dataList.add(new DrawerItem(NAME,EMAIL,AVATARresID));
dataList.add(new DrawerItem("Account", R.mipmap.ic_account));
dataList.add(new DrawerItem("Tuoi Tour", R.mipmap.ic_events));
dataList.add(new DrawerItem("Prenota Tour", R.mipmap.ic_action_search));
// dataList.add(new DrawerItem("My Favorites")); // adding a header to the list
dataList.add(new DrawerItem("Others")); // adding a header to the list
dataList.add(new DrawerItem("Contatti", R.mipmap.ic_about));
dataList.add(new DrawerItem("Tutorial", R.mipmap.ic_help));
mRecyclerView = (RecyclerView) findViewById(R.id.RecyclerView);
mRecyclerView.setHasFixedSize(true);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mAdapter = new MyAdapter(dataList, mSelectedPositions);
mRecyclerView.setAdapter(mAdapter);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mDrawerToggle = new ActionBarDrawerToggle(this,mDrawerLayout,toolbar,
R.string.drawer_open, R.string.drawer_close){
#Override
public void onDrawerOpened(View drawerView) {...}
#Override
public void onDrawerClosed(View drawerView) {...}
};
// Drawer Listener set to the Drawer toggle
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerToggle.syncState();
mRecyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(this, mRecyclerView, new RecyclerItemClickListener.OnItemClickListener() {...});
}
}
I've solved it!
My solution is twofold: I both update the dataList dataStructure on the fly after the user's login, and then make this update persistent with SharedPreferences.
The reason why the following instructions were not working:
String usr = data.getStringExtra("username");
String mal = data.getStringExtra("email");
this.NAME = usr; this.EMAIL=mal;
was because the RecyclerView.Adapter mAdapter (the object holding my data) did not have any way to know that a certain change took place, and it therefore didn't update its data.
For it to know that a certain change had actually occurred, first of all I had to modify the ArrayList<DrawerItems> dataList, and secondly I had to notify the Adapter of the change with the method mAdapter.notifyItemChanged(0) (similarly to how it happens with the Observer-Observable pattern). This way the Navigation Drawer is immediately updated with the new dataList.
This wasn't all. Simply updating the dataList on the fly was a volatile solution, since every time the user changes activity and then goes back to the MainActivity, the NavigationDrawer is initialized again with the old data (losing any acquired information during past states, and therefore loading empty NAME and EMAIL variables). Thus, in order to make the account information persistent was necessary to save them into SharedPreferences.
This is the code of onActivityResult() updating the navigation drawer on the fly and also saving the account's information persistently into SharedPreferences:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
// Check which request we're responding to
if (requestCode == PICK_ACCOUNT_REQUEST) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// The user picked a contact.
String usr = data.getStringExtra("username");
String mail = data.getStringExtra("email");
SharedPreferences usrData = getSharedPreferences(usr_loggedin, MODE_PRIVATE);
SharedPreferences.Editor editor = usrData.edit();
editor.clear();
editor.putBoolean("usraccount",true).commit();
editor.putString("username",usr).commit();
editor.putString("email",mail).commit();
dataList.remove(0);
dataList.add(0,new DrawerItem(usr,mail,AVATARresID));
mAdapter.notifyItemChanged(0);
}
}
}
This is where in MainActivity I check if the user is logged in, and if so the account information are loaded from SharedPreferences:
//...
String NAME,EMAIL; int AVATARresID;
#Override
protected void onCreate(Bundle savedInstanceState) {
//...
//Initializing
SharedPreferences usrData = getSharedPreferences(usr_loggedin, MODE_PRIVATE);
AVATARresID = R.mipmap.aka;
// Add Drawer Item to dataList
dataList = new ArrayList<>();
dataList = prepareDatalist(dataList, NAME, EMAIL, AVATARresID);
mRecyclerView = (RecyclerView) findViewById(R.id.RecyclerView);
mRecyclerView.setHasFixedSize(true);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mAdapter = new MyAdapter(dataList, mSelectedPositions);
if(usrData.contains("usraccount")){
String usr,mail;
usr = usrData.getString("username",usr_loggedin);
mail = usrData.getString("email",usr_loggedin);
dataList.remove(0);
dataList.add(0,new DrawerItem(usr,mail,AVATARresID));
mAdapter.notifyItemChanged(0);
}
mRecyclerView.setAdapter(mAdapter);
//... ...
}
As a side not, to solve my problems I had to notice (with a great deal of debugging) that after the method onActivityResult() has finished, the MainActivity's onCreate() is not called a second time and the execution of the class ends with the end of onActivityResult().
For this reason I couldn't rely only on SharedPreferences to update the user's information. In fact even though the SharedPreferences do their job well by making all the needed information available everywhere in the project, when the onCreate method isn't called a second time, there would be no way of update the RecyclerView.Adapter with the new information and no extra code, making the SharedPreferences to become pointless.
For these reasons, updating MainActivity's account fields was impossible to perform without the mAdapter.notifyItemChanged(0), which did the job on the fly.
Having said that, any subsequent call to onCreate() method in MainActivity would load the account information from SharedPreferences() until the user wouldn't logout somewhere else.
I cannot comment, so posting as an answer - you are updating the variables, but are you updating the DrawerLayout's view itself? I assume you have some kind of TextViews or EditTexts for the Strings, are you calling .setText(NAME)/.setText(EMAIL) on them? Can't quite make this out from your question. :)
In your navigation drawer I believe you are using the textviews to display the name and email. You need to pass these values with the help of a listener and then set these texts in the drawer text views.
Create a listener which has a method which takes name and email
public interface ChangeListener {
void displayNameAndEmail(String name, String email );
}
You implement this listener in the drawer menu and set the text views in this method based on the values received.
#Override
private void displayNameAndEmail(String name, String email ) {
mEmailTextView.setText(email);
mNameTextView.setText(name);
};
In your onActivityResult() call this method and pass the values
ChangeListener.displayNameAndEmail(name, email );

Trying to change TextView String

I´ve been looking for answers, and have tried a lot of things, but nothing is working...
So, Im doing what I think is a simple app (I just started learning)
So I have an activity sending a couple of string to another where a couple of TextViews should chnage ther values to the new String, but this is not happening. Here you have the code:
public class LoginActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
Intent intent = getIntent();
String mail = intent.getStringExtra(MainActivity.MAIL);
String password = intent.getStringExtra(MainActivity.PASSWORD);
setContentView(R.layout.fragment_login);
TextView displayMailSetter = (TextView) findViewById(R.id.mailView);
displayMailSetter.setText(mail);
displayMailSetter.postInvalidate();
TextView displayPasswordSetter = (TextView)findViewById(R.id.passwordView);
displayPasswordSetter.setText(password);
displayPasswordSetter.postInvalidate();
displayMailSetter.postInvalidate();
setContentView(R.layout.activity_login);
}
}
Try taking out these lines of code:
displayMailSetter.postInvalidate();
// Don't take out your displayPasswordSetter initilization and setText
displayPasswordSetter.postInvalidate();
displayMailSetter.postInvalidate();
setContentView(R.layout.activity_login);
Change these lines of code:
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
to
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_login);
and take out the origional (right under the intents).
setContentView(R.layout.fragment_login);
The problem was that you were setting the layout to 3 different layouts. The first and third were the same layout, but didn't have the TextViews. The first and third are unnessecary, you should only set the layout once. Once you set it to fragment_login, the layout had the TextViews, set the text of them, but the layout was then changed to a layout without the TextViews.

Categories

Resources