I have two activities A and B which is extending one Base class Main and this Base class has one Framelayout in its layout which we are including in both of the activities A and B respective layouts.
I am checking the instance creation of fragment in Fragment which I am also inflating when I go into particular acitivity.
Here my code is :
public class BaseAcitvity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base_acitvity);
}
}
Here is my FirstActivity::
public class FirstActivity extends BaseAcitvity {
public FirstFragment firstFragment ;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.firstactivitylayout);
firstFragment = new FirstFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.card_view_layout,firstFragment).commit();
Button buttonclick = (Button)findViewById(R.id.clickfirstactivity);
buttonclick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(getApplicationContext(),SecondActivity.class);
startActivity(intent);
}
});
}
}
public class SecondActivity extends BaseAcitvity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.secondactivity);
FirstFragment fragment = FirstFragment.getInstance();
if(fragment == null)
{
fragment = new FirstFragment();
}
else {
FragmentManager fragmentManager = getFragmentManager();
if(fragment !=null)
{
fragmentManager.beginTransaction().replace(R.id.card_view_layout,fragment).commit();
}
}
}
}
And The Fragment is ::
public class FirstFragment extends Fragment {
private static FirstFragment currentInstance;
FirstFragment () {
currentInstance = this;
}
public static synchronized FirstFragment getInstance() {
if (currentInstance == null)
currentInstance = new FirstFragment();
return currentInstance;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
return inflater.inflate(R.layout.fragment_one, container, false);
}
}
Now my issue is if I have already created the instance of fragment in FirstActivity and checking the singleInstance in Fragment , the at the time of SecondActivity why the OncreatView() of fragment doesn't call where the instance gives not null.
Please help me..so that is there any way to call OncreateView() to inflate the fragmentLayout.
Related
I am having a fragment that contains for example one button, I want to allow the Activity containing the fragment to change this button view like for example color and title or src Image.
What's the best way to do that ?
Update : sorry If I wasn't clear enough but I want the activity to change the whole view as it's likes , like setting the padding, the color or anything.
It will create the view programmatically and the fragment should replace the old view by the new one and change the view's ID so that the fragment code isn't affected. And If i created methods in the fragment that takes these views when should the Main activity call them ? since the activity has to wait for the layout of the fragment to be created.
1. You must get you fragment from your activity
val fragment = supportFragmentManager.findFragmentByTag("tag")
or
val fragment = supportFragmentManager.findFragmentById(R.id.fragment)
2. Create a method that will do what you wants in you fragment and call this method from the activity
fragment.hideButton()
or you can use interface
Try this way according to your requirement
public abstract class BaseFragment extends Fragment {
BaseActivity yourActivity;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
yourActivity = (BaseActivity) context;
}
#Override
public void onDetach() {
yourActivity = null;
super.onDetach();
}
public void refreshview(){}
public void setDada(Data data){}
#override
publicn void onStart(){
yourActivity.setCurrentOpenedFragment(this);
}
}
Create the BaseActivity class
public abstract class BaseActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void setCurrentOpenedFragment(BaseFragment currentFragment){}
}
Extends the BaseFragment in your fragment i.e.
public class YourFragment extends BaseFragment{
View view;
Button button;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment, container, false);
button = (Button)view.findViewById(R.id.button);
return view;
}
#override
publicn void onStart(){
super.onStart();
//yourActivity.setCurrentOpenedFragment(this);
}
Data data;
#override
public void setDada(Data data){
this.data = data;
}
#Override
public void refreshview() {
button.setcolor(data.getcolor());
}
}
Write the below line of code in your Activity class
public class YourActivity extends BaseActivity{
public static final byte NONE = -1;
public static final byte HOME = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_activity);
changeFragment(new YourFragment(), HOME);
initview();
}
public void initview(){
Button b = (Button)findViewById(R.id.button);
b.setOnClickListener(new OnClickListener(){
if(currentFragmentOnDrawer != null){
Data data = new Data();
data.setColor(getResource().getcolor(R.color.red));
currentFragmentOnDrawer.setDada(data);
currentFragmentOnDrawer.refreshview()
}
});
}
BaseFragment currentFragmentOnDrawer;
#Override
public void setCurrentOpenedFragment(BaseFragment currentFragment) {
super.setCurrentOpenedFragment(currentFragment);
this.currentFragmentOnDrawer = currentFragment;
}
public void changeFragment(Fragment targetFragment, byte state) {
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
ft.replace(R.id.main_fragment, targetFragment, "" + state);
ft.addToBackStack("" + state);
ft.commit();
}
}
Hope it will help for you
I have a Fragment that displays a list using my class ListRecyclerViewAdapter that extends RecyclerView.Adapter:
public class ListFragment extends Fragment {
private ListRecyclerViewAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
adapter = new ListRecyclerViewAdapter(context, itemsToDisplay);
...
}
public ListRecyclerViewAdapter getListAdapter() {
return adapter;
}
}
When I try to get the Adapter from an Activity that has the above Fragment, I get null:
public class DataActivity extends FragmentActivity {
#Override
protected void onResume() {
super.onResume();
listFragment = new ListFragment(itemsToDisplay);
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_list_container, listFragment).commit();
ListRecyclerViewAdapter wantedAdapter = listFragment.getAdapter();
}
}
Why is that? It looks to me like the Fragment's method onCreateView() was not called at the point when I call listFragment.getAdapter().
Fragment is not created when you are trying to call the method.So check is the fragment is attached before accessing the adapter.
public ListRecyclerViewAdapter getListAdapter() {
if(this.isAdded() && adapter!=null){
return adapter;
}
return null;
}
Also load the fragment in oncreate of activity and call the adpter reference method in onresume
public class DataActivity extends FragmentActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listFragment = new ListFragment(itemsToDisplay);
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_list_container, listFragment).commit();
}
#Override
protected void onResume() {
super.onResume();
ListRecyclerViewAdapter wantedAdapter = listFragment.getAdapter();
}
}
As soon as it created, it called listfragment adapter. so, the UI creation will take some time , but the flow flowed to that line. so it return null. you can acheive this in following way.
public class ListFragment extends Fragment {
LoadAdapter loadAdapter;
private ListRecyclerViewAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
adapter = new ListRecyclerViewAdapter(context, itemsToDisplay);
...
}
public ListRecyclerViewAdapter getListAdapter() {
return adapter;
}
interface LoadAdapter {
public void onAdapterLoaded();
}
public void setOnAdapterLoad(LoadAdapter loadAdapter){
this.loadAdapter = loadAdapter;
}
#Override
public void onResume(){
loadAdapter.onAdapterLoaded();
}
}
Now the activity code as follows:
public class DataActivity extends FragmentActivity {
#Override
protected void onResume() {
super.onResume();
listFragment = new ListFragment(itemsToDisplay);
listFragment.setOnAdapterLoad(new LoadAdapter(){
#Override
public void onAdapterLoaded(){
ListRecyclerViewAdapter wantedAdapter = listFragment.getAdapter();
}
});
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_list_container, listFragment).commit();
}
}
Hope this helps.
I'm creating an app, and I have a doubt on how to communicate between fragments, I know I must communicate to the parent activity and etcetera my question is more best practice oriented. My app consists of a MainActivity with a navigation drawer which depending on the selection calls a fragment and puts it on the main screen.
I have 2 fragments which via a button need to call another fragment (I can convert it to an activity with no problem) that opens the camera to scan a barcode (BarScanFragment) (https://github.com/dm77/barcodescanner).
My question is it possible to know which fragment called the BarScanFragment so I can send the argument to the correct fragment, and how do I achieve it.
BarScanFragment.java
public class BarScanFragment extends Fragment implements ZXingScannerView.ResultHandler{
private ZXingScannerView mScannerView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mScannerView = new ZXingScannerView(getActivity());
return mScannerView;
}
#Override
public void onResume() {
super.onResume();
mScannerView.setResultHandler(this);
mScannerView.startCamera();
}
#Override
public void onPause() {
super.onPause();
mScannerView.stopCamera();
}
#Override
public void handleResult(Result result) {
Log.i("TAG", result.getText());
Bundle args = new Bundle();
args.putString("barcodeScan", result.getText());
}
FragmentA.java
......
......
barcodeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment content = new BarScanFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.flFragmentContainer, content).addToBackStack("TRADEIN")
.commit();
/*Intent intent = new Intent(rootView.getContext(), BarcodeScannerActivity.class);
startActivity(intent);*/
}
});
Fragment b.java
.....
.....
barcodeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment content = new BarScanFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.flFragmentContainer, content).addToBackStack("INFOPRODUCT")
.commit();
/*Intent intent = new Intent(rootView.getContext(), BarcodeScannerActivity.class);
startActivity(intent);*/
}
});
Take a look on setTargetFragment and getTargetFragment. It's the easiest way to communicate back and forth between fragment.
Here there is a little example https://github.com/alexfu/TargetFragmentExample
You can add a parameter to the BarScanFragment's constructor:
public BarScanFragment(int creatorFragment) {
// Do something with creatorFragment
}
Save "creatorFragment" values in your activity:
public static final int FRAGMENT_1 = 0;
public static final int FRAGMENT_2 = 1;
Then in your button listeners create the BarScanFragment with a specific value:
Fragment content = new BarScanFragment(MainActivity.FRAGMENT_1);
or
Fragment content = new BarScanFragment(MainActivity.FRAGMENT_2);
Declare callbacks in your activity and call methods from another fragment using these callbacks
public interface Callback1 {
void callbackMethod1();
}
public interface Callback2 {
void callbackMethod2();
}
public class Activity extends ActionBarActivity implements Callback1, Callback2 {
Fragment1 mFragment1;
Fragment2 mFragment2;
#Override
public void callbackMethod1() {
mFragment2.method2();
}
#Override
public void callbackMethod2() {
mFragment1.method1();
}
}
public class Fragment1 extends Fragment {
Callback1 callback;
#Override
public void onAttach(android.app.Activity activity) {
super.onAttach(activity);
callback = (Callback1) getActivity();
}
void callMethodOfFragment1() {
callback.callbackMethod1();
}
#Override
public void onDetach() {
super.onDetach();
callback = null;
}
public void method1() {
do_sth_in_fr2();
}
}
public class Fragment2 extends Fragment {
Callback2 callback;
#Override
public void onAttach(android.app.Activity activity) {
super.onAttach(activity);
callback = (Callback2) getActivity();
}
void callMethodOfFragment2() {
callback.callbackMethod2();
}
#Override
public void onDetach() {
super.onDetach();
callback = null;
}
public void method2() {
do_sth_in_fr1();
}
}
i made an interface in the fragment class kind of like a listener to send a string from the Fragment to the Activity. what is the best way to also send strings in the opposite direction? from activity to fragment? so there is now an interface in the fragment, so do i have to make another interface in the Activity to send strings in the other direction, or is there a better way?
the fragment class:
public class FragmentHeadless extends Activity implements FragmentHeadlessFragment.OnTimeRequestedListener {
FragmentTransaction transaction;
Button button;
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_headless);
button = (Button) findViewById(R.id.button1);
textView = (TextView) findViewById(R.id.textView1);
FragmentManager fragmentManager = getFragmentManager();
transaction = fragmentManager.beginTransaction();
transaction.add(new FragmentHeadlessFragment(), "processorFragment");
transaction.commit();
}
#Override
public void passString(String stringFromFragment) {
textView.setText(stringFromFragment);
Toast.makeText(this, "String passed from fragment " + stringFromFragment, Toast.LENGTH_SHORT).show();
}
}
the activity class
public class FragmentHeadlessFragment extends Fragment {
private OnTimeRequestedListener listener;
String tempString = "";
Activity activity;
Handler handler;
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
handler = new Handler();
new Thread(){
public void run() {
SystemClock.sleep(3000);
handler.post(new Runnable() {
#Override
public void run() {
// pass string to activity
passData("test string from fragment with 3 second delay");
}
});
} // end run
}.start();
} // end onCreate
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof OnTimeRequestedListener) {
listener = (OnTimeRequestedListener) activity;
} else {
throw new ClassCastException(activity.toString()
+ " must implemenet OnTimeRequestedListener");
}
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
activity = getActivity();
setRetainInstance(true);
}
public interface OnTimeRequestedListener {
public void passString(String timeNumberString);
}
public void passData(String data) {
listener.passString(data);
}
}
since you have an instance to the fragment, you can just call the function you need via the activitiy:
instead of :
transaction.add(new FragmentHeadlessFragment(), "processorFragment");
use:
private FragmentHeadlessFragment mFragment;
...
mFragment=new FragmentHeadlessFragment();
transaction.add(mFragment, "processorFragment");
and when you wish, call:
mFragment.foo(myInt,myString,...) ;
btw, why do you have a field for the transaction?
I have a problem with accessing activity's method from fragment.
Or anything int the activity from the fragment.
Here's fragment code:
public class MainFragment extends Fragment {
private MainActivity ma = (MainActivity) getActivity();
public SipAudioCall call = null;
public SipManager mSipManager = null;
public SipProfile mSipProfile = null;
public MainFragment() {
// TODO Auto-generated constructor stub
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Create a new TextView and set its text to the fragment's section
// number argument value.
LinearLayout mLinearLayout = (LinearLayout) inflater.inflate(R.layout.main_layout, container, false);
final Button callbtn = (Button) mLinearLayout.findViewById(R.id.callbtn);
final Button endbtn = (Button) mLinearLayout.findViewById(R.id.endbtn);
callbtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
callbtn.setVisibility(View.GONE);
endbtn.setVisibility(View.VISIBLE);
ma.initiateCall();
}
});
Maybe casting the activity is wrong?
Thx in advance
I'm guessing that the fragment is not attached to the activity when u call getActivity(). Try to initialize the activity reference in the fragment method onAttach().
So something like this:
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
ma = (MainActivity) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " Not MainActivity class instance");
}
}