Unable to access a ListFragment - java

I have a MainActivity like this
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} }
and this
public class MyListFragment extends ListFragment implements OnItemClickListener {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.list_fragment, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.Planets, android.R.layout.simple_list_item_1);
setListAdapter(adapter);
getListView().setOnItemClickListener(this);
int count = getListView().getCount();
getListView().setSelection(getListView().getCount() - 1);
test();
}
public void test(){
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.Planets, android.R.layout.simple_list_item_1);
setListAdapter(adapter);
getListView().setOnItemClickListener(this);
int count = getListView().getCount();
getListView().setSelection(getListView().getCount() - 1);
Toast.makeText(getActivity(), "ccc"+count, Toast.LENGTH_SHORT)
.show();
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Toast.makeText(getActivity(), "Item: " + position, Toast.LENGTH_SHORT)
.show();
} }
The activity_main.xml has a
fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.example.mike.mqtt.MyListFragment"
android:id="#+id/fragment_content" />
When the application starts I get the fragment_content filled up with some rows.
How can I access the ListFragment(MyListFragment.java) from inside the MainActivity.java in the onCreate.
When I press a button the get the ListFragment content count, and to set focus at the end of the list.
I have no idea.Thank you.

MyListFragment fragment = (MyListFragment) getFragmentManager().findFragmentById(R.id.fragment_content)

I avoid using fragments in XML as it alows me to replace them on-the-fly. I usually use something like this:
private MyListFragment mListFragment;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// the usual business
FragmentManager fm = getSupportFragmentManager();
if (savedInstanceState == null) {
// the activity opened for the first time, we create and commit fragment
mListFragment = new MyListFragment();
fm.beginTransaction().replace(android.R.id.content, f).commit);
} else {
// activity is recreating so it's safe to find already added fragments
mListFragment = fm.findFragmentById(android.R.id.content);
}
}

Related

Listen DialogFragment dismiss event from ViewPager Fragment

There are lot of (duplicate) questions and answers are available, I went through almost all of them and failed. On reference of this question, I made some changes recently.
Brief : In my app, MainActivity holds Fragment View Pager and FrangmentA,B and C. FrangmentA Shows a DialogFragment CDialog onClik. After dismissing CDialog I need to Call FragmentA's doReload() which is not happening here.
MainActivity
protected void onCreate(Bundle savedInstanceState){
...
mSectionsPageAdapter = new FragmentAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.container);
setupViewPager(mViewPager);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
int defaultValue = 0;
int page = getIntent().getIntExtra("One", defaultValue);
mViewPager.setCurrentItem(page);
}
private void setupViewPager(ViewPager viewPager)
{
FragmentAdapter adapter = new
FragmentAdapter(getSupportFragmentManager());
adapter.addFragment(new FragmentA(), "FragA");
adapter.addFragment(new FragmentB(), "FragB");
adapter.addFragment(new FragmentC(), "FragC");
viewPager.setAdapter(adapter);
}
FragmentA
public class FragmentA extends Fragment implements CDialog.Dismissed{
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
...
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
FragmentManager fm = getActivity().getFragmentManager();
DialogFragment f = new CDialog();
f.show(fm, "CDialog");
}
});
#Override
public void dialogDismissed() {
Log.e(DFD_1, "dialogDismiss Called" );// <-- This is not working*
doReload();
}
}
And CDialogue
public class CDialog extends DialogFragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
....
return v;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
...
dfd_1.setOnClickListener(
new View.OnClickListener() {
public void onClick(View v) {
getDialog().dismiss(); //<--when this happens*
}
});
}
#Override
public void onDismiss(DialogInterface dialog) {
if (getActivity() != null && getActivity() instanceof Dismissed) {
((Dismissed) getActivity()).dialogDismissed();
}
super.onDismiss(dialog);
}
public interface Dismissed {
public void dialogDismissed(); //<-- FragmentA implements this
}
}
You can always have direct callback to your Fragment itself.
First step, is to set targetFragment using setTargetFragment():
DialogFragment#setTargetFragment(Fragment fragment, int requestCode);
I do it this way:
public void showDialogFragment(Fragment targetFragment, AppCompatDialogFragment appCompatDialogFragment, int requestCode) {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
appCompatDialogFragment.setTargetFragment(targetFragment, requestCode);
fragmentTransaction.add(appCompatDialogFragment, appCompatDialogFragment.getClass().getSimpleName());
fragmentTransaction.commitAllowingStateLoss();
}
and then call to this method to open dialog fragment as:
public static final int RC_CDIALOG = 111;
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
showDialogFragment(FragmentA.this, new CDialog(), RC_CDIALOG);
}
});
Then, in your DialogFragment's onDismissListener(), have some code like below:
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (getTargetFragment() instanceof FragmentA)
((FragmentA) getTargetFragment()).doReload();
}
What you did this way is:
Show Dialog Fragment "CDialog" along with telling it that your target fragment is "FragmentA" whose reference you can use incase you have something to do with it. In your case you had to call doReload();

Android fragments looks overhead

MainActivity has 2 buttons and when I click the buttons I want 2 fragments to appear in the same page.But when I click on itsMeContact button, it comes up, but when I click on the PhoneContact button, I overwrite the other one.
MainActivity.java
public class MainActivity extends AppCompatActivity {
Button itsMeContact,phoneContact;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
itsMeContact= (Button) findViewById(R.id.its_me_contact);
phoneContact= (Button) findViewById(R.id.phone_contact);
itsMeContact.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager manager = getFragmentManager();
UserFragment userFragment = new UserFragment();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.frame_layout, userFragment, "userFragment");
transaction.commit();
}
});
phoneContact.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager manager = getFragmentManager();
FragmentB fragmentB = new FragmentB();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.frame_layout, fragmentB, "fragg");
transaction.commit();
}
});
}
}
UserFragment.java
public class UserFragment extends Fragment {
RecyclerView recyclerView ;
UserAdapter userAdapter ;
ArrayList<Person> arrayList ;
private LinearLayoutManager layoutManager;
Button itsMeContact,phoneContact;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.fragment_user,container,false);
recyclerView = view.findViewById(R.id.recycler_view);
itsMeContact= view.findViewById(R.id.its_me_contact);
layoutManager = new LinearLayoutManager(getActivity());
layoutManager.scrollToPosition(0);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
arrayList=new ArrayList<Person>();
initial();
return view;
}
private void initial() {
Factory.getInstance().user().enqueue(new Callback<List<User>>() {
#Override
public void onResponse(Call<List<User>> call, Response<List<User>> response) {
// textView.setText(response.body().get(0).name);
userAdapter= new UserAdapter(response.body(), getActivity());
recyclerView.setAdapter(userAdapter);
}
#Override
public void onFailure(Call<List<User>> call, Throwable t) {
}
});
}
}
FragmentB.java
public class FragmentB extends Fragment {
TextView textView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.fragment_fragment_b,container,false);
textView=view.findViewById(R.id.textView);
textView.setText("naber");
return view;
}
}
Your advice important for me !
Thank you very much
My app:
enter image description here
Each Fragment transaction you did use the same framelayout : "R.id.frame_layout".
So this is normal if "it looks overhead". If you want 2 fragments displayed in a same layout, you should use 2 differents framelayout.

ANDROID fragment inside a custom dialog in activity

I would like to put a fragment inside a custom dialog in activity.
I receive this error:
java.lang.IllegalArgumentException: No view found for id 0x7f0c007e (copyworld.rebootcw:id/container_schedule1) for fragment FragmentGiorno{418215c0 #0 id=0x7f0c007e}
This is my code:
layout.xml
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="200dp"
android:layout_below="#+id/spinner_dialog_schedulazione"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:id="#+id/container_schedule1">
</FrameLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Popup_schedule();
}
//******POPUP PER LA SCHEDULAZIONE******************
public void Popup_schedule() {
dialog_schedule=new Dialog(MainActivity.this);
dialog_schedule.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
dialog_schedule.setContentView(R.layout.dialog_schedule);
dialog_schedule.setCancelable(false);
lp = new WindowManager.LayoutParams();
window = dialog_schedule.getWindow();
lp.copyFrom(window.getAttributes());
lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
dialog_schedule.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window = dialog_schedule.getWindow();
window.setAttributes(lp);
FragmentGiorno fragment = new FragmentGiorno();
android.support.v4.app.FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.container_schedule1, fragment);
fragmentTransaction.commit();
dialog_schedule.show();
}
}
How I add a fragment inside a custom dialog in MainActivity.java that extend Activity?
Try this
dialog_schedule.findViewById(R.id.container_schedule1)
Instead Of
R.id.container_schedule1
In your Code
If you want to load fragment inside dialog then you can use DialogFragment instead.
Below is the working example of using DialogFragment.
public class Demo extends DialogFragment{
View mainView;
LinearLayout layoutArrow;
Bundle bundle;
ArrayList<BookingDetail> bookingDetails;
View.OnClickListener onClickListener;
public static Demo newInstance(#NonNull ArrayList<BookingDetail> bookingDetails) {
Demo alertPopUpMapReservedBedInfo = new Demo();
Bundle args = new Bundle();
args.putSerializable("bookingDetails", bookingDetails);
alertPopUpMapReservedBedInfo.setArguments(args);
return alertPopUpMapReservedBedInfo;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_TITLE, R.style.InvitationDialogWithSimpleAnim);
bundle = getArguments();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mainView = inflater.inflate(R.layout.alert_info, container, false);
getDialog().setCanceledOnTouchOutside(true);
return mainView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
init();
}
private void init() {
layoutArrow = (LinearLayout) mainView.findViewById(R.id.layoutArrow);
FragmentGiorno fragment = new FragmentGiorno();
android.support.v4.app.FragmentTransaction fragmentTransaction =
this.getChildFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.container_schedule1, fragment);
fragmentTransaction.commit();
}
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if(onClickListener!=null){
onClickListener.onClick(null);
}
}
}
And call it by,
Demo newFragment = Demo.newInstance(bookingDetails);
newFragment.show(ft,"dialog");

NULL in Adapter in Fragment (FragmentPagerAdapter) after screen rotation

I was looking answer in similar topics but nothing works for me. I have Activity which has a fragment. This fragment has adapter. Everything is fine even if I rotate screen, but when I rotate screen and try to update adapter (for example by sort items in adapter - method sort) I get NULL on adapter.
When Activity starts first time this is happening:
ON CREATE (ACTIVITY)
SETUP VIEW PAGER (ACTIVITY)
CONSTRUCTOR (FRAGMENT)
SET DATA IN ADAPTER (ACTIVITY)
ON CREATE (FRAGMENT)
CREATE ADAPTER (FRAGMENT)
ON CREATE VIEW (FRAGMENT)
UPDATE ADAPTER (FRAGMENT)
ON ACTIVITY CREATED (FRAGMENT)
In the second time when I rotate screen:
ON CREATE (ACTIVITY)
CONSTRUCTOR (FRAGMENT)
ON CREATE (FRAGMENT)
CREATE ADAPTER (FRAGMENT)
SETUP VIEW PAGER (ACTIVITY)
CONSTRUCTOR (FRAGMENT)
SET DATA IN ADAPTER (ACTIVITY)
ON CREATE VIEW (FRAGMENT)
UPDATE ADAPTER (FRAGMENT)
ON ACTIVITY CREATED (FRAGMENT)
So the problem is that in activity method super.onCreate(savedInstanceState) the fragment is recreated istelf. I was trying pass NULL for super.onCreate(null) and also checking if savedInstance is NULL, changing FragmentPagerAdapter for FragmentStatePagerAdapter, and many others things. What I want to do is save and get fragment, adapter in proper way or just make activity start everytime like in the first time.
PART OF MAIN ACTIVITY
public class MainActivity extends AppCompatActivity {
private TabLayout tabLayout;
private ViewPager viewPager;
SongsFragment songsFragment;
TabAdapter tabAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
setContentView(R.layout.activity_main);
//init work
tabAdapter = new TabAdapter(getSupportFragmentManager());
songsFragment = new SongsFragment();
songsFragment.setData(database.getSongs(readOption(), readOrder()));
tabAdapter.addFragment(songsFragment, "TAB");
viewPager.setAdapter(tabAdapter);
tabLayout.setupWithViewPager(viewPager);
}
public void sort() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setItems(R.array.sorts, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if(which == 0) writeSort("number", "ASC");
else if(which == 1) writeSort("number", "DESC");
else if(which == 2) writeSort("title", "ASC");
else if(which == 3) writeSort("title", "DESC");
songsFragment.setData(database.getSongs(readOption(), readOrder()));
songsFragment.updateAdapter();
}
}).show();
}
}
FRAGMENT
public class SongsFragment extends Fragment {
private RecyclerView recyclerView;
List<Song> songs = new ArrayList<>();
SongsAdapter adapter;
public SongsFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v("TAG", "onCr");
if(!(savedInstanceState == null || !savedInstanceState.containsKey("list"))) {
songs = (List<Song>) savedInstanceState.getSerializable("list");
}
createAdapter();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.v("TAG", "onCrV");
View view = inflater.inflate(R.layout.fragment_songs, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.fragment_songs_SongsList);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(adapter);
updateAdapter();
return view;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("list", (Serializable) songs);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
public void setData(List<Song> songs) {
this.songs = songs;
}
public void createAdapter() {
adapter = new SongsAdapter(getContext(), songs);
}
public void updateAdapter() {
adapter.clear();
adapter.addAll(songs);
adapter.notifyDataSetChanged();
}
}
FRAGMENT PAGER ADAPTER
public class TabAdapter extends FragmentStatePagerAdapter {
List<Fragment> fragments = new ArrayList<>();
List<String> titles = new ArrayList<>();
public TabAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
public void addFragment(Fragment fragment, String title) {
fragments.add(fragment);
titles.add(title);
}
}

How do I update a ListView in a Fragment?

I´m trying to udate a ListView in a Fragment the only way it actually will work is if I instanciate the fragment new. adpter.notifyDataSetChanged() is not working? Whay not? Here the Code an Activity and the Fragment:
public class TimerList extends Activity{
private DataSource datasource;
TimerListFragment timerfragment;
IntervalListFragment intervalfragment;
public List<TimerObject> values;
public String name;
public String intervals;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.interval_fragment_container);
datasource = new DataSource(this);
datasource.open();
values = datasource.getAllComments();
if (savedInstanceState == null) {
Toast.makeText(getApplicationContext(), "MADE NEW FRAGMENTS", Toast.LENGTH_SHORT).show();
timerfragment = new TimerListFragment();
intervalfragment = new IntervalListFragment();
}
}
public void delete(Long position){
TimerObject timerobject = datasource.getTimerObject(position);
datasource.deleteComment(timerobject);
values = datasource.getAllComments();
}
#Override
protected void onStart() {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_container, timerfragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
super.onStart();
}
And my Fragment :
public class TimerListFragment extends ListFragment {
List<TimerObject> values ;
Activity a;
ArrayAdapter<TimerObject> adapter;
ListView lv;
#Override
public void onCreate(Bundle savedInstanceState) {
setHasOptionsMenu(true);
values = ((TimerList)getActivity()).getValues();
setBar();
adapter = new ArrayAdapter<TimerObject>(getActivity(), android.R.layout.simple_list_item_1, values);
setListAdapter(adapter);
super.onCreate(savedInstanceState);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
((TimerList)getActivity()).play(Long.valueOf(position));
super.onListItemClick(l, v, position, id);
}
public void setBar(){
ActionBar actionbar = getActivity().getActionBar();
actionbar.setTitle("Timer List");
}
public void update(){
setBar();
Toast.makeText(getActivity(), "UPDATE", Toast.LENGTH_LONG).show();
values = ((TimerList)getActivity()).getValues();
adapter.notifyDataSetChanged();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.interval_timer_list,
container, false);
return view;
}
#Override
public void onStart() {
update();
lv = getListView();
lv.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView parent, View view, int position, long id) {
final TimerObject selected = adapter.getItem(position);
final Dialog d = new Dialog(getActivity());
d.setContentView(R.layout.interval_deletetimer_dialog);
d.setTitle("Delete " + selected.getComment() + "?" );
ImageButton delete = (ImageButton) d.findViewById(R.id.delete);
delete.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
((TimerList)getActivity()).delete(Long.valueOf(selected.getId()));
update();
}
});
d.show();
return true;
}
});
super.onStart();
}
I tried to do something similar, and I solved this problem by simply redoing the fragment transaction.
In your case, you could accomplish this within your onListItemClick() method.
you could copy this:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_container, timerfragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
into your onListItemClick() method in your fragment
This resets the fragment. Unfortunately, this would also set your list to null. A way around this would be to make the values list a private static variable of the TimerListFragment class. That way, any changes made to the list will remain 'saved', and when you reload your fragment, it will be populated with the newly updated list.
hope this helps

Categories

Resources