I have multiple activities and fragments. I would like to set toolbar in BaseActivity (so set it only once). But need an acces to the toolbar from fragment (method like - show, hide, changeTitle etc.)
Any suggestion?
I have tried solution below, but when I want to hide fragment, NPException is shown
public abstract class BaseActivity extends AppCompatActivity {
Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResource());
configureToolbar();
}
protected abstract int getLayoutResource();
private void configureToolbar() {
toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
public void hideToolbar() {
toolbar.setVisibility(View.GONE);
}
My activity
public class MyActivity extends BaseActivity() {
}
I call hideToolbar in fragment like:
public class MyFragment extends Fragment() {
onCreate() {
((Myactivity)getActivity).hideToolbar();
}
I have include something like yours in my project. This is sample. You can take reference from it.
BaseActivity.java class:
public abstract class BaseActivity extends AppCompatActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResource());
}
protected abstract int getLayoutResource();
}
ToolBarActivity.java class:
public abstract class ToolbarActivity extends BaseActivity {
protected Toolbar toolbar;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View contentView = findViewById(R.id.flToolbarContentContainer);
if (contentView instanceof ViewGroup) {
((ViewGroup) contentView)
.addView(LayoutInflater.from(this)
.inflate(getToolbarLayoutResource()
, (ViewGroup) contentView, false));
}
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
#Override
protected int getLayoutResource() {
return R.layout.activity_toolbar;
}
protected abstract int getToolbarLayoutResource();
public void showToolbar() {
toolbar.setVisibility(View.VISIBLE);
}
public void hideToolbar() {
toolbar.setVisibility(View.GONE);
}
}
activity_toolbar.xml layout file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rlToolbarContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_toLeftOf="#+id/pbToolbarActivity"
android:background="#color/blue_panel_day_background"
android:theme="#style/ToolbarTheme" />
<FrameLayout
android:id="#+id/flToolbarContentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/toolbar" />
</RelativeLayout>
MainActivity.java class:
public class MainActivity extends ToolbarActivity {
#Override
protected int getToolbarLayoutResource() {
return R.layout.activity_main;
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
homeFragment = HomeFragment.newInstance();
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.llMainActivityContainer, homeFragment)
.commit();
}
}
activity_main.xml layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/llMainActivityContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
Now, in Fragment class, apply:
((ToolbarActivity) getActivity()).showToolbar();
((ToolbarActivity) getActivity()).hideToolbar();
From Fragment
getActivity().getSupportActionBar();
Use:
public abstract class BaseActivity extends AppCompatActivity {
private Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResource());
configureToolbar();
}
protected abstract int getLayoutResource();
private void configureToolbar() {
toolbar = (Toolbar) findViewById(R.id.toolbar);
// changes made here, try to find if getSupportActionBar() is null or not after setting it - setSupportActionBar
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
// How and where you calling this method ?
public void hideToolbar() {
toolbar.setVisibility(View.GONE);
}
To access ActionBar from Fragment try the below method
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
You can now access all the methods of ActionBar
Related
i want to access toolBar in MyActivity which extends BaseActivity can access Toolbar in MainActivity.
BaseActivity
public abstract class BaseActivity extends AppCompatActivity{
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_container_base);
Toolbar toolBar = (Toolbar) findViewById(R.id.tool_bar);
}
}
MyActivity
public class MyActivity extends BaseActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// here i want to access BaseActivity Toolbar
}
Set your toolbar with setSupportActionBar in your BaseActivity:
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_container_base);
Toolbar toolBar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
}
Then get the toolbar from getSupportActionBar after super.onCreate in MainActivity:
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getSupportActionBar();
}
You can't cast an ActionBar to Toolbar, but if you really want to access to the toolbar, then change it to an instance variable:
protected Toolbar toolbar;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_container_base);
toolBar = (Toolbar) findViewById(R.id.tool_bar);
// ...
With protected modifier you can access to toolbar in your MainActivity.
I made a BaseActivity class to initiate menus, toolbars etc on different activities. Using the BaseActivity works as needed for the toolbar and menu, but doesn't show any additional content I want to add there - like my textView. Can you help out please?
Here's my BaseActivity:
public abstract class BaseActivity extends AppCompatActivity
{
private DrawerLayout mDrawerLayout ;
private ActionBarDrawerToggle mToggle ;
private NavigationView mNavView ;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResourceId());
}
protected abstract int getLayoutResourceId();
public void initToolbar(int toolbarId)
{
Toolbar myToolbar = (Toolbar) findViewById(toolbarId);
setSupportActionBar(myToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
assert myToolbar != null;
}
public void initMenu() {
// Stuff in here
}
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId() ;
if(mToggle.onOptionsItemSelected(item)) {
return true ;
}
return super.onOptionsItemSelected(item);
}
And the actual Activity extending BaseActivity:
public class SaunaLight extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initToolbar(R.id.custombar);
initMenu();
TextView sauna = (TextView) findViewById(R.id.sauna);
}
#Override
protected int getLayoutResourceId() {
return R.layout.activity_sauna_light;
}
}
So currently my TextView sauna isn't displayed - I just get a white screen.
Had a very stupid mistake. Turned out, my custom action bar had a weird height and it was covering the whole layout. Got it fixed! Sorry for wasting your time!
I am trying to add DataBinding to my app. In my app, I have a BaseActivity which has a Toolbar and a FrameLayout. FrameLayout is container for activities' which extend the BaseActivity. How can I add databinding to both my BaseActivity and the extending activities?
I'll share my code without DataBinding:
Here is my BaseActivity.java:
public class BaseActivity extends AppCompatActivity {
#Override
public void setContentView(#LayoutRes int layoutResID) {
LinearLayout container = (LinearLayout) getLayoutInflater().inflate(R.layout.activity_base, null);
FrameLayout activityContent = (FrameLayout) container.findViewById(R.id.activityContent);
getLayoutInflater().inflate(layoutResID, activityContent, true);
super.setContentView(container);
Toolbar toolbar = (Toolbar) container.findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
if (menuItem.getItemId() == android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(menuItem);
}
public void setTitle(String title) {
getSupportActionBar().setTitle(title);
}
}
Here is activity_base.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<include
android:id="#+id/toolbarLayout"
layout="#layout/toolbar" />
<FrameLayout
android:id="#+id/activityContent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</layout>
Here is the activity which extends BaseActivity: CardRecyclerViewActivity.java:
public class CardRecyclerViewActivity extends BaseActivity {
RecyclerView recyclerView;
ReplikAdapter adapter;
ArrayList<Replik> replikListesi;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_card_recyclerview);
replikListesiniDoldur();
adapter = new ReplikAdapter(replikListesi, this, R.layout.item_card_replik);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setAdapter(adapter);
setTitle(R.string.cardRecylerView);
}
public void replikListesiniDoldur() {
replikListesi = new ArrayList<Replik>();
replikListesi.add(new Replik(R.drawable.harvey1, "Ben ihtimallere oynamam. Adama oynarım.", "Harvey Specter"));
replikListesi.add(new Replik(R.drawable.harvey2, "Avukatlık doktorluğa çok benzer, acıtana kadar bastırırsın ve böylece nereye bakman gerektiğini anlarsın.", "Harvey Specter"));
replikListesi.add(new Replik(R.drawable.harvey3, "İşte aramızdaki fark bu; Sen küçük kaybetmek istiyorsun ben ise büyük kazanmak.", "Harvey Specter"));
replikListesi.add(new Replik(R.drawable.harvey4, "Benim hayallerim yok, hedeflerim var.", "Harvey Specter"));
}
}
Okey, I add DataBinding to my BaseActivity.java like that:
public class BaseActivity extends AppCompatActivity {
#Override
public void setContentView(#LayoutRes int layoutResID) {
ActivityBaseBinding binding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.activity_base, null, false);
getLayoutInflater().inflate(layoutResID, binding.activityContent, true);
super.setContentView(binding.getRoot());
setSupportActionBar(binding.toolbarLayout.toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
if (menuItem.getItemId() == android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(menuItem);
}
public void setTitle(String title) {
getSupportActionBar().setTitle(title);
}
}
activity_base.xml with DataBinding:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="#+id/toolbarLayout"
layout="#layout/toolbar" />
<FrameLayout
android:id="#+id/activityContent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</layout>
But I am not sure how to add DataBinding to my extending activities in this scenerio. Could you help me out, please?
Might be late for this question.
Your BaseActivity should looks like following.
public abstract class BaseActivity<B extends ViewDataBinding, T extends BaseViewModel> extends AppCompatActivity {
protected B dataBinding;
protected T baseViewModel;
protected void bindView(int layoutId) {
dataBinding = DataBindingUtil.setContentView(this, layoutId);
}
#Override
protected void onDestroy() {
baseViewModel.detachView();
super.onDestroy();
}
}
Your MainActivity should looks like following.
public class MainActivity extends BaseActivity<ActivityMainBinding, MainActivityViewModel> implements MainActivityView, View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindView(R.layout.activity_main);
baseViewModel = new MainActivityViewModel();
baseViewModel.attachView(this);
dataBinding.btnPerformOperation.setOnClickListener(this);
}
#Override
public void OnDataLoad(String item) {
dataBinding.setIsLoading(false);
startActivity(new Intent(MainActivity.this, SecondActivity.class).putExtra("result", item));
}
#Override
public void OnError(Throwable throwable) {
}
#Override
public void onClick(View v) {
dataBinding.setIsLoading(true);
baseViewModel.loadNextData();
}
}
Reference source code can be download from here.
Hope this helps you.
how about this?
BaseActivityViewModel.java
public class BaseActivityViewModel {
public void onClick() {
Log.i("BaseActivityViewModel | onClick", "111111111111");
}
}
activity_base.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="model"
type="kr.changhoonjin.textmvvmwithextend.BaseActivityViewModel"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="#{()->model.onClick()}"
android:text="base"/>
<FrameLayout
android:id="#+id/layout_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</layout>
BaseActivity.java
public class BaseActivity extends AppCompatActivity {
private ActivityBaseBinding binding;
#Override protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_base);
binding.setModel(new BaseActivityViewModel());
}
protected <T extends ViewDataBinding> T putContentView(#LayoutRes int resId) {
return DataBindingUtil.inflate(getLayoutInflater(), resId, binding.layoutContainer, true);
}
}
MainActivityViewModel.java
public class MainActivityViewModel {
public void onClick2() {
Log.i("MainActivityViewModel | onClick2", "2222222222222");
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="model"
type="kr.changhoonjin.textmvvmwithextend.MainActivityViewModel"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="#{()->model.onClick2()}"
android:text="main"/>
</LinearLayout>
</layout>
MainActivity.java
public class MainActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = putContentView(R.layout.activity_main);
binding.setModel(new MainActivityViewModel());
}
}
It will be same as you have done in BaseActivity, instead of inflate just use setContentView
private ActivityCardRecyclerviewBinding binding;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this,R.layout.activity_card_recyclerview);
}
In my App call demo extends ListActivity and I want to use back button navigation icon . Please suggest me how could be possible
example: public class demo extends ListActivity and I don't want to change ListActivity to extends another activity
write this line:
assert getActionBar() != null;
getActionBar().setDisplayHomeAsUpEnabled(true);
in ListActivity getSupportActionBar is not supported. so you should use Actionbar
or you can use delegate method for that like this:
#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(SomeActivity.this);
}
});
and make sure that your AppCompatCallback import v7 lib.
import android.support.v7.app.AppCompatCallback;
import android.support.v7.app.AppCompatDelegate;
best approach is use Delegate for ListActivity.
I have a static v4.app.Fragment in an AppCompatActivity's xml, and everything shows up when I launch the app, but once I enter another activity and comeback, or switch to another app and switch back, the fragment cannot be seen, while the Log.d of the fragment shows that the fragment exists somewhere. I have also tried using getsupportfragmentmanager.add.commit to programmatically add the fragment, and it has the same result
activity_main.xml
...
<FrameLayout
android:id="#+id/content_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<fragment
android:id="#+id/fragment"
android:name="xxx.xxx.xxx.Fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
<android.support.design.widget.FloatingActionButton
...
MainActivity.java
#BindView(R.id.toolbar) Toolbar toolbar;
#BindView(R.id.fab) FloatingActionButton fab;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(MainActivity.this);
...
No onResume, onCreateView, etc
XFragment.java
public class XFragment extends Fragment {
#BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout swipeRefreshLayout;
#BindView(R.id.recyclerView) RecyclerView recyclerView;
// and a lot of other variables
public XFragment() {
}
public static XFragment newInstance(boolean isSearch) {
XFragment xFragment = new XFragment();
return xFragment;
}
#Override
public void onResume() {
Log.d(TAG, "onResume");
super.onResume();
//initiate variables
inflateRecyclerView();
//etc
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
View view = inflater.inflate(R.layout.fragment_x, container, false);
ButterKnife.bind(this, view);
return view;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Parcelable parcelable = llm.onSaveInstanceState();
outState.putParcelable("LM", parcelable);
}
#Override
public void onViewStateRestored(#Nullable Bundle savedInstanceState) {
Log.d(TAG, "onViewStateRestored");
super.onViewStateRestored(savedInstanceState);
if (savedInstanceState != null) {
llm = savedInstanceState.onRestoreInstanceState(savedInstanceState.getParcelable("LM"));
}
}
public void inflateRecyclerView() {
//use retrofit to call api
}
P.S.: when I add it dynamically, I hide the , findViewById in the activity, then use
XFragment f = new XFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, f).commit();
Sorry, I know what is causing the problem. I have been using a library call DynamicBox, and it seems that it is causing the problem. I don't know if I have do something wrong or there are bugs on that library yet.
Yay...