After changing to the Android Navigation Component I encountered some problems with migrating my Activity Transitions to the corresponding Fragment Transitions.
Specifically, it appears that the EnterTransition of a Fragment doesn't apply to it's Child Fragments.
I've set up a test activity that contains an OuterTestFragment, which in turn consists of a TextView and another fragment, InnerTestFragment.
A button in the activity then replaces the OuterTestFragment with a new OuterTestFragment to see if the contents transition smoothly.
Here are the relevant classes:
Activity:
public class PlaygroundActivity extends AppCompatActivity {
public static final ArrayList<String> strings = new ArrayList<>();
static {
strings.add("sgdgdgsdfggggggggsdgsdfgsd\nsdsdgsdfgds\ndfgsd\nsdsdgsdfgds\ndfgsd");
strings.add("sgdgdgsdfgggg\nggggsndfgsd\nsdsdgsdfgds\ndfgsd");
strings.add("sgdgsd\nsdsdgsdfgds\ndfgsd");
strings.add("sgdgdgsdfggfgds\ndfgsd");
strings.add("sgdgdgsdfggggggggsdg");
}
int count = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_playground);
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainerOuter, OuterTestFragment.getInstance("This is an inner text", "Outer text!"))
.commit();
}
public void replace(View v) {
getSupportFragmentManager().beginTransaction()
.setReorderingAllowed(true)
.addToBackStack("replaced")
.replace(R.id.fragmentContainerOuter, InnerTestFragment.getInstance(count++ >= 4 ? "Default" : strings.get(count)))
.commit();
}
}
OuterTestFragment:
public class OuterTestFragment extends TransitionedFragment {
private static final String ARG_OUTER_TEXT = "OuterTestFragment:outerText";
private static final String ARG_INNER_TEXT = "OuterTestFragment:innerText";
private String innerText;
private String outerText;
public static OuterTestFragment getInstance(String inner, String outer) {
OuterTestFragment outerFragment = new OuterTestFragment();
Bundle args = new Bundle();
args.putString(ARG_OUTER_TEXT, outer);
args.putString(ARG_INNER_TEXT, inner);
outerFragment.setArguments(args);
return outerFragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
innerText = getArguments().getString(ARG_INNER_TEXT);
outerText = getArguments().getString(ARG_OUTER_TEXT);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.test_fragment_outer, container, false);
((TextView) layout.findViewById(R.id.textOuter)).setText(outerText);
getFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, InnerTestFragment.getInstance(innerText))
.commit();
return layout;
}
}
TransitionedFragment:
public abstract class TransitionedFragment extends Fragment {
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TransitionInflater inflater = TransitionInflater.from(getContext());
setEnterTransition(inflater.inflateTransition(R.transition.default_transition));
setReenterTransition(inflater.inflateTransition(R.transition.default_transition));
setSharedElementEnterTransition(inflater.inflateTransition(R.transition.scaled_img_clip_transition));
}
}
Inner Test Fragment:
public class InnerTestFragment extends Fragment {
private static final String ARG_TEXT = "InnerTestFragment:text";
private String text;
public static InnerTestFragment getInstance(String text) {
InnerTestFragment frgmt = new InnerTestFragment();
Bundle args = new Bundle();
args.putString(ARG_TEXT, text);
frgmt.setArguments(args);
return frgmt;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
text = getArguments().getString(ARG_TEXT);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.test_fragment_inner, container, false);
((TextView) layout.findViewById(R.id.text)).setText(text);
return layout;
}
}
Any help is much appreciated, as the Transition API drives me nuts....
You may show transitions with the setEnterTransition method.
Fragment fragment = InnerTestFragment.getInstance(innerText);
Fade enterFade = new Fade(); //can be any transition, SlideTransition or Inflated Transitions
enterFade.setDuration(300); //Duration of transition in ms
fragment.setEnterTransition(enterFade);
getFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, fragment)
.addToBackStack(fragment.getClass().getSimpleName())
.commit();
Try to add a background color to the child fragment...
Related
HomeFragment.java:
public class HomeFragment extends Fragment {
FirebaseAuth fAuth;
String userId;
Button logout;
FirebaseFirestore fStore;
EditText name,no,mail;
public HomeFragment() {
}
public static HomeFragment newInstance(String param1, String param2) {
HomeFragment fragment = new HomeFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
name=(EditText)view.findViewById(R.id.fname);
mail=(EditText)view.findViewById(R.id.emailid);
no=(EditText)view.findViewById(R.id.phone);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
}
I have my xml file(fragment_home.xml) which contains three TextView's which Iam unable to modify and my app crashes when trying to do so. I need to set my textview with the data from the firebase.
Please help me find a solution
I have 3 fragments that are generated from the same class file. These three fragments exist within a ViewPager and a FragmentStatePagerAdapter.
They are in sliding tabs. They are created once and never dismissed or deleted or go out of memory.
The app works fine so far, but I need to figure out how to make the fragments have knowledge of their own index (1,2, or 3).
Is there some code like:
int myIndex = summonTheAllKnowingThing.getWhatFragmentThisIsPlease();
That I can add somewhere in the following code?
public class BlankFragment extends Fragment implements View.OnClickListener {
private boolean isDone = false;
EditText persons_name;
Spinner disc1_spinner;
Spinner disc2_spinner;
Spinner disc3_spinner;
Spinner fee1_spinner;
Spinner fee2_spinner;
EditText custom_disc;
EditText custom_fee;
Button doneButton;
public BlankFragment() {
// Required empty public constructor
}
public static BlankFragment newInstance() {
BlankFragment fragment = new BlankFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_blank, container, false);
doneButton = (Button) v.findViewById(R.id.doneButton);
doneButton.setOnClickListener(this);
return v;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// getView().findViewById(R.id.
persons_name = (EditText) getView().findViewById(R.id.NAME);
disc1_spinner = (Spinner) getView().findViewById(R.id.DISC1);
disc2_spinner = (Spinner) getView().findViewById(R.id.DISC2);
disc3_spinner = (Spinner) getView().findViewById(R.id.DISC3);
custom_disc = (EditText) getView().findViewById(R.id.customDISC);
custom_fee = (EditText) getView().findViewById(R.id.customFEE);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.doneButton:
if MainActivity.is1Done
doneButton.setBackgroundColor(Color.RED);
MainActivity.name1 = persons_name.getText().toString();
break;
}
}
}
Best approach is to pass the index while creating the fragment in pager adapter as in
#Override
public Fragment getItem(int position) {
return BlankFragment.newInstance(position);
}
and BlankFragment would be
public class BlankFragment extends Fragment implements View.OnClickListener {
private int myIndex; //<-- access it for getting its index
//.. some other variables
public BlankFragment() {
// Required empty public constructor
}
public static BlankFragment newInstance(int indexInPager) {
BlankFragment fragment = new BlankFragment();
Bundle bundle = new Bundle();
bundle.putInt("index",indexInPager);
fragment.setArguments(bundle);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
myIndex = getArguments().getInt("index");
View v = inflater.inflate(R.layout.fragment_blank, container, false);
doneButton = (Button) v.findViewById(R.id.doneButton);
doneButton.setOnClickListener(this);
return v;
}
//.. some other code
}
I want to create fragment with Arguments,
and refer to this post [ Do fragments really need an empty constructor? ].
But not work, I don't know how to fix it.
Code:
Fragment
public class TestFragment extends Fragment {
private final static String BUNDLE_TITLE = "title";
private RelativeLayout rootView;
private String title = "";
public static TestFragment newInstance(String titleName){
Bundle bundle = new Bundle();
bundle.putString(BUNDLE_TITLE,titleName);
TestFragment testFragment = new TestFragment();
testFragment.setArguments(bundle);
return testFragment;
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
if (rootView == null) {
rootView = (RelativeLayout) inflater.inflate(R.layout.find_mac, container, false);
}
return rootView;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle data = getArguments();
if(data != null){
this.title = getArguments().getString(BUNDLE_TITLE,"");
}
}
String getTitle() {
return title;
}
}
And in Activity,
#Override
protected void onStart() {
super.onStart();
TestFragment testFragment = TestFragment.newInstance("hello");
Log.d("debug","get title:"+testFragment.getTitle());
}
The Log show only "get title:",
I can't get the title "hello" word.
This is because when you calling:
TestFragment testFragment = TestFragment.newInstance("hello");
Log.d("debug","get title:"+testFragment.getTitle());
the testFragment fragment is not yet finished created. Because it is an asynchronous process.
So, you need to create a listener in activity to tell that the fragment is created, then in it, you can get the title.
You can read Communicating with Other Fragments for implementing the listener.
i have made two fragments in my app.
1st fragment (EditFrag) and 2nd fragment (ListTable). i want to transfer the value of 1st fragment(from EditText of 1st fragment) to the recyclerView of 2nd fragment.
how should i do that.....i can't find right documentation.
Thank you for your concern!
MainActivity:
public class MainActivity extends AppCompatActivity implements EditFrag.TransferValue{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListTable frag1=new ListTable();
FragmentManager manager=getSupportFragmentManager();
FragmentTransaction transaction=manager.beginTransaction();
transaction.add(R.id.table_value_container,frag1,"fragment");
transaction.commit();
EditFrag frag2=new EditFrag();
FragmentManager manager1=getSupportFragmentManager();
FragmentTransaction transaction1=manager1.beginTransaction();
transaction1.add(R.id.table_container,frag2,"fragment_edit");
transaction1.commit();
}
#Override
public void sendValue(String value) {
Log.d("ashu","button is pressed");
ListTable listTable = (ListTable) getSupportFragmentManager().findFragmentById(R.id.table_value_container);
listTable.receiveValue(value);
}
}
2nd fragment(ListTable):
public class ListTable extends Fragment {
public TextView myEditText1;
private RecyclerView recyclerView;
public ListTable() {
// Required empty public constructor
}
public static ListTable newInstance(String param1, String param2) {
ListTable fragment = new ListTable();
Bundle args = new Bundle();
Log.d("ashu", "new instance is called :");
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("ashu", "oncreata called by inflating: ");
View view = inflater.inflate(R.layout.fragment_list_table, container, false);
myEditText1 = (TextView) container.findViewById(R.id.table_value);
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
MyAdapter a = new MyAdapter();
recyclerView.setAdapter(a);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
public void receiveValue(String value) {
myEditText1.setText(value);
}
public class MyAdapter extends RecyclerView.Adapter<MyDataViewHolder> {
#Override
public MyDataViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Log.d("ashu", "oncreateview holder of adapter ia called");
LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.fragment_list_table, parent, false);
return new MyDataViewHolder(view);
}
#Override
public void onBindViewHolder(MyDataViewHolder holder, int position) {
holder.myEditText.setText("Table: " + position);
}
#Override
public int getItemCount() {
return 10;
}
}
public class MyDataViewHolder extends RecyclerView.ViewHolder {
public TextView myEditText;
public MyDataViewHolder(View itemView) {
super(itemView);
Log.d("ashu", "DAta view holder is called: ");
myEditText = (TextView) itemView.findViewById(R.id.table_value);
}
}
}
1st Fragment(EditFrag):
public class EditFrag extends Fragment {
TransferValue SendData;
EditText inputvalue;
Button click;
#Nullable
#Override
public View onCreateView(final LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.edit_frag_layout, container, false);
inputvalue = (EditText) view.findViewById(R.id.edit_text);
click = (Button) view.findViewById(R.id.click);
click.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String received = inputvalue.getText().toString();
SendData.sendValue(received);
}
});
return view;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
SendData = (TransferValue) context;
} catch (ClassCastException e) {
Log.d("ashu", "implement the methods");
throw new ClassCastException("implemented the methods");
}
}
public interface TransferValue {
public void sendValue(String value);
}
}
create the instance of fragment2 from where want to receive the value to:
public static Fragment2 createInstance(String data) {
Fragment2 fragment = new Fragment2();
Bundle bundle = new Bundle();
bundle.putString("keyword", data);
fragment.setArguments(bundle);
return fragment;
}
and the get the data as below:
Bundle bundle = getArguments();
if (bundle != null) {
String data = bundle.getString("data");
}
You can use bundle in an order to pass data to fragment:
Example:
// Set bundle as arguments to the fragment
Bundle bundle = new Bundle();
bundle.putString(MyKey1, MyValue1);
bundle.putString(MyKey2, MyValue2);
MyFragment myFragment = new MyFragment();
myFragment.setArguments(bundle);
Inside onCreateView of fragment:
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.repairer_part_details_fragment, container, false);
String value1 = getArguments().getString(MyKey1);
String value2 = getArguments().getString(MyKey2);
return view;
}
There are many ways to do that. I see your codes above, and 2 fragments loaded at the same time. I usaually use one of 2 ways below to do it.
The first solution: You can use this link using obserable pattern to communication 2 fragments.
The second solution: you can use EventBus lib for communication, it 's very simple
Hello I am using Fragment in my android application. I need to get the view which I can get using.
mNoteEditText = rootView.findViewById(R.id.noteEditText);
This mNoteEditText is require to access in onBackPressed so every view reference I need to make them static variable because of Fragment class is static. I know to make every view to static variable is not good approach. How this I can make such that I dont need to make any static variable of the view.
public class NotesActivity extends Activity {
private int bookId;
private int chapterId;
private static EditText mNoteEditText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notes);
// get data from intent that sent from home activity
bookId = getIntent().getIntExtra("book_id", -1);
chapterId = getIntent().getIntExtra("book_id", -1);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new NoteFragment()).commit();
}
}
/**
* A note fragment containing a note layout.
*/
public static class NoteFragment extends Fragment {
public NoteFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_notes,
container, false);
mNoteEditText = (EditText) rootView.findViewById(R.id.noteEditText);
return rootView;
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
// get database instance
MySQLiteOpenHelper db = MySQLiteOpenHelper.getInstance(this);
Notes note = new Notes();
note.setBookId(bookId);
note.setChapterId(chapterId);
note.setNote(mNoteEditText.getText().toString());
}
}
Please help and thanks in advance.
A Fragment has a Method called getView(). With it you can get the View of the Fragment as long as it is attached to an Activity.
View view = fragment.getView();
But if you are looking for a View inside the Fragment you can also just get it with findViewById() from the Activity. Again the Fragment has to be attached to the Activity for this to work.
BUT you should not do that. Nothing outside the Fragment should have anything to do with something inside the Fragment. Write public methods in the Fragment to interact with it. Try something like this:
public static class NoteFragment extends Fragment {
private EditText noteEditText;
public NoteFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_notes, container, false);
this.noteEditText = (EditText) rootView.findViewById(R.id.noteEditText);
return rootView;
}
// I added the following 3 methods to interact with the Fragment
public boolean isEmpty() {
final String text = this.noteEditText.getText().toString();
return text.isEmpty();
}
public String getText() {
return this.noteEditText.getText().toString();
}
public void setText(String text) {
this.noteEditText.setText(text);
}
}
And now in your Activity you can do this:
public class NotesActivity extends Activity {
private int bookId;
private int chapterId;
private NoteFragment noteFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notes);
// get data from intent that sent from home activity
bookId = getIntent().getIntExtra("book_id", -1);
chapterId = getIntent().getIntExtra("book_id", -1);
if (savedInstanceState == null) {
this.noteFragment = new NoteFragment();
getFragmentManager().beginTransaction().add(R.id.container, this.noteFragment).commit();
}
// Now you can interact with the Fragment
this.noteFragment.setText("some text");
...
if(!this.noteFragment.isEmpty()) {
String note = this.noteFragment.getText();
...
}
}
}