Android Eclipse to Android Studio - android

I'm moving my app from minSdk 8 targetSdk 19 built in Eclipse to minSdk 14 targetSdk 22 built in Android Studio, since the announcement of withdrawal of Eclipse support.
Rather than allowing Android Studio to perform a conversion, I wanted to create a new project and manually port my code over.
I'm stuck.
I have a main activity which extends from AppCompatActivity and uses a navigation drawer and a toolbar, which all works fine. My fragment loads ok too, until I try to reference the toolbar.
My main activity code is:
public class MainActivity extends AppCompatActivity implements BlankTestFragment.OnFragmentInteractionListener {
private Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
...
...
My loaded fragment code is:
public class BlankTestFragment extends Fragment {
...
private Toolbar toolbar;
...
public static BlankTestFragment newInstance(String param1, String param2) {
BlankTestFragment fragment = new BlankTestFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public BlankTestFragment() {
// Required empty public constructor
}
public final static String TAG = BlankTestFragment.class.getSimpleName();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
toolbar = ((AppCompatActivity)getActivity()).getSupportActionBar();
}
The last line reports:
Incompatible Types:
Required: android.support.v7.widget.Toolbar
Found: android.support.v7.app.Actionbar
So, what's going wrong? Where is the Actionbar reference coming from?
SOLUTION
In MainActivity I added:
public static Toolbar getToolbar(){
return toolbar;
}
In my test fragment, in onAttach, I added:
toolbar = MainActivity.getToolbar();
toolbar.setTitle("hello");
SOLUTION 2
It turns out that just a small error in my test fragment prevented my original implementation from working.
In MainActivity I had set the toolbar to be a SupportActionBar. So when I tried
toolbar = ((AppCompatActivity)getActivity()).getSupportActionBar();
in the fragment, I had set toolbar to be
private Toolbar toolbar;
but by then it wasn't a ToolBar, so I changed it to
private ActionBar toolbar;
and everything worked fine.

Where is the Actionbar reference coming from?
The return value of getSupportActionBar() is an instance of android.support.v7.app.ActionBar, as is indicated in the JavaDocs. You cannot assign that to a Toolbar field, as Toolbar does not inherit from ActionBar.
Under the covers, setSupportActionBar() takes your Toolbar and wraps it in another object. I do not see an easy way to get the Toolbar back. So, try to work with the ActionBar wrapper that getSupportActionBar() returns.

Remove code getActivity()).getSupportActionBar();. Simply replace it with code getting the toolbar from MainActivity by calling a public get method from that Activity. CommonsWare gave a good hint already.

Related

getSupportActionBar setSubtitle only shows after activity recreation

I have a generic
MyActivity extends AppCompatActivity
I don't override the toolbar with a custom xml defined toolbar, just use the generated one Android provides.
I can set the title via your normal
getSupportActionBar().setTitle("foo");
but setting the subtitle via
getSupportActionBar().setSubtitle("bar");
doesn't set it. It remains blank. I'm doing this onCreate()
(I feel I've done this many times before with no fail)
Although I've noticed if I visit another activity, then return, the subtitle would then show... not on orientation change, not on recreate() but only when I'm returning from an activity.
I'm experiencing this on 5.0 and 7.0
For the time being I'll likely define my own Toolbar and move forward since that seems where most people have solutions for this same problem.
Relevant code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_replenishment_list);
ButterKnife.bind(this);
MyApplication.getInstance().getComponent().inject(this);
setupUI();
}
private void setupUI() {
setupActionBar();
}
private void setupActionBar() {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
//TODO: not working unless activity is recreated...
// explore custom xml defined toolbar
//actionBar.setTitle("different title than what is defined in manifest"); <-- this does work, but not this
actionBar.setSubtitle(UserUtil.getFormattedFirstNameLastName(userService.getUserFromJWT(), this));
}
}
I have put the below code in my onCreate() method.
ActionBar actionBar = getActionBar();
if (actionBar==null) {
System.out.println("TEST NULL");
} else {
System.out.println("TEST NOT NULL");
}
The result is null. When I add the toolbar first it works fine.
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getActionBar();
actionBar.setSubtitle("TESTING");
Your getSupportActionBar or getActionBar will return null if you didn't set toolbar to it. You need to set the toolbar to your action bar before using getSupportActionBar or getActionBar.

Android how to use Toolbar in ListActivity?

I made a ListActivity:
public class NoteListActivity extends ListActivity{
}
and the following methods are no longer available:
setSupportActionBar(toolbar);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
But I can use:
setActionBar(toolbar);
getActionBar().setHomeButtonEnabled(true);
getActionBar().setDisplayHomeAsUpEnabled(true);
Note that I used Support library in other activities in the same project. It means I have the correct gradle dependency added.
How do I use ListActivity and android.support.v7.widget.Toolbar ?
You can't do that in ListActivity.
If you want to access getSupportActionBar(), you need to extend your class with AppCompatActivity.
My Suggestion : Don't use ListActivty as you want to use ToolBar. Create an Activity and then only have ListView within that Activity. It'll work just fine.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppCompatCallback callback = new AppCompatCallback() {
#Override
public void onSupportActionModeStarted(ActionMode actionMode) {
}
#Override
public void onSupportActionModeFinished(ActionMode actionMode) {
}
#Nullable
#Override
public ActionMode onWindowStartingSupportActionMode(ActionMode.Callback callback) {
return null;
}
};
AppCompatDelegate delegate = AppCompatDelegate.create(this, callback);
delegate.onCreate(savedInstanceState);
delegate.setContentView(R.layout.saved_report_activity);
Toolbar toolbar= (Toolbar) findViewById(R.id.toolbar);
delegate.setSupportActionBar(toolbar);
delegate.getSupportActionBar().setDisplayShowHomeEnabled(true);
toolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
NavUtils.navigateUpFromSameTask(SavedReportActivity.this);
}
});
AppCompatActivity is the direct child class of FragmentActivity of support v4 .Read this article
http://android-developers.blogspot.it/2015/04/android-support-library-221.html
so for your requirement, public class NoteListActivity extends AppCompatActivity {...}
Just change your dependency,Like :
compile "com.android.support:appcompat-v7:22.1.0"
I was able to solve this by adding a support library toolbar style and then adding the style to my list activity in the manifest.
In styles.xml:
<style name="FullscreenActionBarStyle" parent="Widget.AppCompat.ActionBar">
In Manifest
<activity android:theme="#style/FullscreenActionBarStyle"
android:name="#string/my_activity_name"
android:label="#string/my_activity_label"/>
This should add a toolbar to your activity that you can add items to and process events with, etc...

How access ActionBar from fragment on Android

On my application I have only one activity (that extends ActionBarActivity ) and various Fragments (that extends Fragment).
When the user click on a menu option, the application change the Fragment.
At this moment I want to change de title and the background color of the ActionBar.
When I try ActionBar actionBar = getActivity().getActionBar(); I got a null exception.
I'm using support library, and on the Activity I'm using android.support.v7.app.ActionBar actionBar = getSupportActionBar(); successfully.
On the Fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.material_cadastro, container, false);
viewHolder = new MaterialViewHolder(view);
ActionBar actionBar = getActivity().getActionBar();
actionBar.setTitle(R.string.inserir_material);
return view;
}
Debuging I got that the Activity is returning OK, but the ActionBar is null:
getActivity() = {br.com.americocarelli.vendasfacil.ui.MenuPrincipal#3b56766f}
getActivity().getActionBar() = null
Override your onAttach(Activity), then cast your Activity to ActionBarActivity, the you can get an ActionBar.
Like:
#Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
ActionBar actionBar=((ActionBarActivity)activity).getSupportActionBar();
}
Since you use the support library (ActionBarActivity), then use ((ActionBarActivity)getActivity()).getSupportActionBar(); to get access to the support action bar.
You are probably building it with build tools >=21, that versions causes activity.getActionBar() returns null, you should use getSupportActionBar() instead.
EDIT: if you get NPE at exactly this line: getActivity(). ... then you are probably referencing it before or after fragment is attached to activity. Could you please paste the context (place, in what function) you are using it?

Dynamically adding fragments from different sources

So I have MainActivity which is going to act as a container to hold two fragments; MainActivity is a subclass of FragmentActivity. The top fragment is a fragment with just a Spinner which is declared as an inner class in MainActivity:
public static class NavigationFragment extends Fragment {
public NavigationFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.navigation_fragment, container, false);
Spinner spinner = (Spinner)rootView.findViewById(R.id.menuSpinner);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.menuArray, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener((MainActivity)getActivity());
return rootView;
}
}
When MainActivity is loaded, I successfully get my top fragment:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.mainContainer, new NavigationFragment())
.commit();
}
}
The bottom fragment is the issue. In another file, I have FragmentA which doesn't really do much yet, but has some ui elements to see if its working; it's a subclass of Fragment. When the user changes the spinner's value, FragmentA will be removed and replaced with FragmentB. I'm trying to add the initial fragment it like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.mainContainer, new NavigationFragment())
.add(R.id.mainContainer, new FragmentA()) // THIS IS THE ONLY NEW LINE AND CAUSES THE ERROR
.commit();
}
}
I'm getting the error can't resolved method add(int, com.mybundle.myapp.FragmentA). I don't understand why, because adding NavigationFragment should be the same as adding FragmentA as they both extend Fragment
My question is, how do I properly dynamically add, then replace, fragments that are not inner classes of the main activity that holds them?
And my other question is, is this the proper way to achieve this kind of navigation flow? I've been working with iOS for several years, so the shift to Android is a little foreign to me as far as design and navigation patterns.
Check your definition files and make sure you use the same import for FragmentTransaction everywhere since FragmentTransaction API comes with the support version also to support android devices running 3.0 version and older

Set a title in Toolbar from fragment in Android

I have been using the latest Toolbar from AppCompatv7 lib.I have placed a textview in the ToolBar ViewGroup And I want to set a title into this Textview from the fragment in my activity.In case of a custom action bar ((ActionBarActivity)getActivity).setcustomView(..) would have done the job.But due to use of this ToolBar I am not able to use that.Also I have implemented a method in my BaseActivity that is inherited by all Activities.This BaseActivity contains my method to initialize a sliding drawer to the left.I have to initialize the initDrawerLayout() method in activity else the drawer would not be initialized.And if I initialize it in fragment its giving me all empty results,neither the toggle button for drawer and nor is the custom title getting set.
This is my initDrawer code..
public void initDrawerLayout(String toolbar_text) {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerRelative = (RelativeLayout) findViewById(R.id.drawer_relative);
if (mDrawerLayout != null) {
findViewById(R.id.drawer_btn_a).setOnClickListener(this);
findViewById(R.id.drawer_btn_b).setOnClickListener(this);
findViewById(R.id.drawer_btn_c).setOnClickListener(this);
findViewById(R.id.drawer_btn_d).setOnClickListener(this);
findViewById(R.id.drawer_btn_e).setOnClickListener(this);
findViewById(R.id.drawer_btn_f).setOnClickListener(this);
findViewById(R.id.drawer_btn_g).setOnClickListener(this);
findViewById(R.id.drawer_btn_h).setOnClickListener(this);
findViewById(R.id.drawer_btn_i).setOnClickListener(this);
findViewById(R.id.drawer_btn_j).setOnClickListener(this);
findViewById(R.id.drawer_btn_k).setOnClickListener(this);
findViewById(R.id.drawer_btn_l).setOnClickListener(this);
findViewById(R.id.my_layout).setOnClickListener(this);
Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
toolbar.setBackground(getResources().getDrawable(R.drawable.icn_actionbar_background));
TextView mTitle = (TextView) toolbar.findViewById(R.id.toolbar_title);
mTitle.setText(toolbar_text);
mTitle.setTypeface(Typeface.DEFAULT_BOLD);
if (toolbar != null) {
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
toolbar.setNavigationIcon(R.drawable.ic_drawer);
mDrawerToggle = new ActionBarDrawerToggle(
this, mDrawerLayout, toolbar,
R.string.drawer_open, R.string.drawer_close
);
mDrawerLayout.setDrawerListener(mDrawerToggle);
toolbar.setNavigationOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (mDrawerLayout.isDrawerOpen(Gravity.LEFT)) {
mDrawerLayout.closeDrawer(Gravity.LEFT);
} else {
mDrawerLayout.openDrawer(Gravity.LEFT);
}
}
});
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
GravityCompat.START);
mDrawerLayout.setScrimColor(getResources().getColor(
android.R.color.transparent));
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayShowTitleEnabled(false);
}
}
And this my code in the fragment..
((FirstActivity) getActivity()).initDrawerLayout(mFirst.name);
where mFirst is a object of class Person
and the toolbar code..
<android.support.v7.widget.Toolbar
android:id="#+id/my_awesome_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize">
<TextView
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="Toolbar Title"
android:textColor="#color/action_text-color"
android:textSize="18sp"
android:textStyle="bold" />
</android.support.v7.widget.Toolbar>
Please help guys..
I do this like this:
from the fragment call
getActivity().setTitle("your title");
But where you call it is important, because if each Fragment has it's own title, then one may override the other accidentally, which may be prevented like:
#Override
public void onResume() {
super.onResume();
Activity activity = getActivity();
if (activity != null) {
activity.setTitle(getString(R.string.my_title));
}
}
For example, two Fragments of the same Pager can not be in resume-state at the same time.
Also you can "cast", to call any function of your parent Activity like this:
YourActivity mYourActiviy = (YourActivity) getActivity();
mYourActivity.yourActivityFunction(yourParameters);
In Kotlin.
In fragment:
(activity as YourActivity).supportActionBar?.title = getString(R.string.your_title)
In activity:
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
If you have setSupportActionBar in Your Activity then you can easily change the toolbar title from your fragment
((YourActivity) getActivity()).getSupportActionBar().setTitle("Your Title");
To allow a Fragment to communicate up to its Activity (to set your Toolbar Title), you can define an interface in the Fragment class and implement it within the Activity as described here: Communicating with Other Fragments.
The answer is writen below in the oncreateview method of fragments.
getActivity().setTitle("your name");
You can create Interface inside the Fragment. check below:-
public class MyFragment extends Fragment {
OnMyFragmentListener mListener;
// Where is this method called??
public void setOnMyFragmentListener(OnMyFragmentListener listener) {
this.mListener = listener;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnMyFragmentListener) {
mListener = (OnMyFragmentListener) context;
mListener.onChangeToolbarTitle("My Fragment"); // Call this in `onResume()`
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
#Override
public void onResume(){
super.onResume();
mListener.onChangeToolbarTitle("My Fragment");
}
// This interface can be implemented by the Activity, parent Fragment,
// or a separate test implementation.
public interface OnMyFragmentListener {
public void onChangeToolbarTitle(String title);
}
}
In Activity:-
public class MyActivity extends AppCompatActivity implements MyFragment.OnMyFragmentListener {
#Override
public void onChangeToolbarTitle(String title){
toolbar.setTitle(title);
}
}
This works for me. :)
This has worked for me, in Kotlin. Put this in your fragment class:
if (activity != null) {
(activity as MainActivity).supportActionBar?.title = getString(R.string.action_history)
}
If somebody struggles with this problem, this may be useful.
Basically you have 4 options, how to handle that:
use an interface in order to communicate with your activity, or any other convenient method, like an event bus.
you call getActivity().setTitle("Title"), but in this case you need to attach your Toolbar to the ActionBar by calling the setSupportActionBar() in your activity.
You can have a public instance of your Toolbar and access that instance from the fragment.
Finally, if you need the instance of your Toolbar(you may want to do something else with), you can simply get it this way:
Toolbar bar=Toolbar.class.cast(getActivity().findViewById(R.id.toolbar));
Well, the last option would solve the problem only if the Toolbar hasn't been passed to the setSupportActionBar method.
If it has been, then you need to call this method in your activity:
supportActionBar.setDisplayShowTitleEnabled(false),
which will solve the problem.
However, I would suggest to use ButterKnife which will make it a little bit cleaner, here an example:
Toolbar actionBar=findById(getActivity(),R.id.actionBar);
actionBar.setTitle("Title");
In Kotlin, I use
fun onAttach(...){
..
activity?.title = "My Title"
}
This work for me :
Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.id_toolbar);
toolbar.setTitle("New Title");
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
FragmentManager.BackStackEntry lastBackStackEntry=null;
int lastBackStackEntryCount = getSupportFragmentManager().getBackStackEntryCount() - 1;
if(lastBackStackEntryCount >= 0 )
{
lastBackStackEntry = getSupportFragmentManager().getBackStackEntryAt(lastBackStackEntryCount);
}
Toast.makeText(MainActivity.this, ""+lastBackStackEntryCount, Toast.LENGTH_SHORT).show();
if(lastBackStackEntryCount == -1)
{
toolbar.setTitle("");
toolbar.setLogo(R.drawable.header_logo);
}
else
{
toolbar.setTitle(lastBackStackEntry.getName());
}
}
});
For me the problem was that for some reason the label was overwritten. I had to change it back to the string resource, in
navigation.xml
inside the fragment tag;
android:label="#string/android_trivia"
You can change the title of your toolbar on the event OnAttach, something like this
var toolbar = activity.FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
toolbar.Title = "New Title";
In your Activity declare the toolbar as public.
public class YourActivity : Activity
{
public Toolbar toolbar;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = .... // initilize your toolbar
}
}
Then, from your fragment
((YourActivity) getActivity()).toolbar.Title = "Your Title";
If you are using a custom toolbar, this will help you:
Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
toolbar.setTitle("Feedback");
You need to set the title in activity commiting the fragment and return the fragment
getSupportFragmentManager().beginTransaction().replace(R.id.main_fragment, mainFragment).commit();
toolbar.setTitle("ShivShambhu");
return contentFragment;
This works for me.
xml
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar_detail"
android:layout_width="match_parent"
android:layout_height="55dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
app:contentInsetStart="0dp"
app:contentInsetStartWithNavigation="0dp"
android:background="#color/tool_bar_color">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:gravity="center">
<TextView
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="#fff"
android:textSize="16sp" />
</LinearLayout>
</android.support.v7.widget.Toolbar>
Find TextView Id from toolbar
if you are using Activity
TextView mTitle = findViewById(R.id.toolbar_title);
mTitle.setText("set your title");
if you are using Fragment
TextView mTitle = view.findViewById(R.id.toolbar_title);
mTitle.setText("set your title");
Here's one simple solution.
In your activity that extends AppCompatActivity, you can do this:
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
The inside its fragment, you can do this:
((AppCompatActivity) getActivity()).getSupportActionBar().setTitle(title);

Categories

Resources