To display another fragment from a fragmentwrapper - android-nested-fragment

I have a custom FragmentWrapper class from which I want to return a new instance every time.
But inside it, I wan't to display another Singleton Fragment from each instance.
i.e.
There should be a single fragment of SingletonFragment.
And, all the instances of FragmentWrapper should display that Singleton fragment.
I tried using nested fragment through fragmentchildmanager but it is not working.
Below is the code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View root = inflater.inflate(R.layout.xxxlayout, container, false);
getChildFragmentManager().beginTransaction()
.replace(R.id.xxxcontainer, singletonfragment)
.commit();
return root;
}
Please suggest.

after commit add following line
getChildFragmentManager().executePendingTransactions();
like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View root = inflater.inflate(R.layout.xxxlayout, container, false);
getChildFragmentManager().beginTransaction()
.replace(R.id.xxxcontainer, singletonfragment)
.commit();
getChildFragmentManager().executePendingTransactions();
return root;
}

Related

How to position controls binding there position into the stage's size using the controller class in JavaFx?

I found some thing similar in this link
How to call functions on the stage in JavaFX's controller file
and here is what I found in one of the answers
StageTrackingSample.java
public class StageTrackingSample extends Application {
#Override public void start(final Stage stage) throws Exception {
final FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"stagetracking.fxml"
)
);
final Parent root = (Parent) loader.load();
final StageTrackingController controller = loader.getController();
controller.initData(stage);
stage.setScene(new Scene(root));
stage.show();
}
public static void main(String[] args) { launch(args); }
}
StageTrackingController.java
public class StageTrackingController {
#FXML private Label stageX;
public void initialize() {}
public void initData(final Stage stage) {
stageX.textProperty().bind(
Bindings.format(
"(%1$.2f, %2$.2f)",
stage.xProperty(),
stage.yProperty()
)
);
}
}
I wanted to position the progressIndicator in the middle of the window, so I tried this in my controller class
Controller.java
public void initInterface(Stage stage) {
progressIndicator.layoutXProperty().bind(stage.widthProperty().divide(2));
progressIndicator.layoutYProperty().bind(stage.heightProperty().divide(2));
}
and this in Main.java
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
final FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
final Parent root = loader.load();
final Controller controller = loader.getController();
final Scene scene = new Scene(root);
controller.initInterface(primaryStage);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
it doesn't work even when I tried passing the scene or the anchorpane(which is defined in the fxml file) as a parameter into initInterface method, it seems that it has problem with binding progressIndicator properties
by using the layoutXProperty and layoutYProperty and binding them to the Stage's width and height you must be trying to put it in the lower right hand corner of the stage. You can achieve this much easier, and JavaFX insists you do so, by using layouts in your scene and making the scene fill the entire area in question.
"From the Javadocs for the layoutX property:
If the node is managed and has a Region as its parent, then the layout region will set layoutX according to its own layout policy. If the node is unmanaged or parented by a Group, then the application may set layoutX directly to position it.
What this means is that the LayoutX/Y properties are controlled by the parent (and so it should be able to 'set' them). However, when you bind them they cannot be set anymore resulting in " A bound value cannot be set" exception."
Here is a good tutorial on regions and how to get things to layout in SceneBuilder as you please. If you're not using SceneBuilder I recommend it.
https://www.youtube.com/watch?v=zvgWgpGZVKc&list=PL6gx4Cwl9DGBzfXLWLSYVy8EbTdpGbUIG&index=35

NullPointerException when notifyDataSetChanged() on ArrayAdapter (ListView in ViewPager)

I have an Activity with ViewPager which manage 2 Fragments using FragmentStatePagerAdapter,
The fragments have ListViews, each of the ListView shows data and I am able to go from Fragment_A to Fragment_B by swipe or item tapping on the ListView of Fragment_A.
I am also able to update the underlying data source for Fragment_B based on the item selected in Fragment_A. But when I try to notifyDataSetChanged() on the DataAdapter of Fragment_B, I am getting NullPointerException .
I want to update the data in Fragment_B according to the item selected in Fragment_A.
Here is my code
public class MyActivity extends FragmentActivity implements AdapterView.OnItemClickListener{
ViewPager viewPager = null;
int mSelectedItemPosition;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_fail_activity);
viewPager = (ViewPager) findViewById(R.id.fail_pager_VP);
viewPager.setAdapter(new pagerAdapter(getSupportFragmentManager()));
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mSelectedItemPosition = position;
viewPager.setCurrentItem(1);
FragmentStatePagerAdapter fspa = (FragmentStatePagerAdapter) viewPager.getAdapter();
Fragment_B item = (Fragment_B) fspa.getItem(1);
item.setData(position);
item.refresh();
}
}
class pagerAdapter extends FragmentStatePagerAdapter {
public pagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
if (position == 0) {
fragment = new Fragment_A();
} else if (position == 1) {
fragment = new Fragment_B();
}
return fragment;
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
String title = "";
if (position == 0) {
return "a_title";
}else if (position == 1) {
return "b_title";
}
}
}
public class Fragment_A extends android.support.v4.app.Fragment {
private ListView frag_a_listView;
DataAdapter dataAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ListView frag_a_listView = (ListView) getActivity().findViewById(R.id.frag_a_LV);
frag_a_listView.setOnItemClickListener((AdapterView.OnItemClickListener) getActivity());
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_fail_main, container, false);
frag_a_listView = (ListView) layout.findViewById(R.id.frag_a_LV);
dataAdapter = new DataAdapter(getActivity(),
R.layout.data_row,
R.id.data_label_TV,
getFrag_aData());
frag_a_listView.setAdapter(dataAdapter);
return layout;
}
private List<String> getFrag_aData() {
...
return someData;
}
}
public class Fragment_B extends android.support.v4.app.Fragment {
ListView frag_b_listView;
List<String> mData;
DataAdapter dataAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ListView frag_b_listView = (ListView) getActivity().findViewById(R.id.frag_b_LV);
frag_b_listView.setOnItemClickListener((AdapterView.OnItemClickListener) getActivity());
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_frag_b, container, false);
frag_b_listView = (ListView) layout.findViewById(R.id.frag_b_LV);
setData(0);
dataAdapter = new DataAdapter(getActivity(),
R.layout.data_row,
R.id.data_label_TV,
mData);
frag_b_listView.setAdapter(dataAdapter);
return layout;
}
public void setData(int position) {
...
mData = some List<String>;
}
public void refresh() {
dataAdapter.notifyDataSetChanged(); <------- this crashes the app
}
}
public class DataAdapter extends ArrayAdapter {
public DataAdapter(Context context, int resource, int textViewResourceId, List objects) {
super(context, resource, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = super.getView(position, convertView, parent);
return convertView;
}
}
here is the crash log
06-25 16:51:46.813 21537-21537/au.myCity.eight E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: au.myCity.eight, PID: 21537
java.lang.NullPointerException: Attempt to invoke virtual method 'void au.myCity.eight.dataAdapter.notifyDataSetChanged()' on a null object reference
at au.myCity.eight.fragments.Fragment_B.refresh(Fragment_B.java:56)
at au.myCity.eight.MyActivity.onItemClick(MyActivity.java:37)
at android.widget.AdapterView.performItemClick(AdapterView.java:305)
at android.widget.AbsListView.performItemClick(AbsListView.java:1146)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3053)
at android.widget.AbsListView$3.run(AbsListView.java:3860)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
After few tries with Log.d and checking some variable references.
The problem was the reference to Fragment_B changed by the time I called dataAdapter.notifyDataSetChanged(), to fix this I used the solution suggested in SO here, thanks to the "Streets Of Boston".
Summery, In the PagerAdapter:
Save a reference to initialized fragments in a SparseArray, use getRegisteredFragment in
onItemClick instead of getItem in MyActivity.
Override instantiateItem and destroyItem as suggested in the link.

Start an instance of activity

How can i start an instance of activity.
My custom activity has a constructor take some paramters.
public class CustomActivity extends Activity {
public CustomActivity(String someParameters) {
}
}
And i create an instance of it. How to start it.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CustomActivity activity = new CustomActivity("TEST");
// how to start to the above activity from this activity
}

Updating ListView data onItemClick

My code does update the ListView when onItemClick is fired but only if I replace the line "inside the onItemClick method"
categoryAdapter.notifyDataSetChanged();
with the line
lv.setAdapter(new CategoryAdapter(categories));
Should I replace the line as indicated above or the notifyDataSetChanged is what I should use? since the docs say that it should update the view as well.
besides, when I do that, the app runs but hitting the back button shuts the app down instead of go back to the last screen which what I like to see.
public class MainActivity extends ActionBarActivity {
ListView lv;
String[] categories = null;
private static String[] failCategories = {"a","b","c};
private static String[] category_a= { "a1","a2"};
CategoryAdapter categoryAdapter = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_categories);
lv = (ListView) findViewById(R.id.lvCategories);
categories = failCategories; //initial set
categoryAdapter = new CategoryAdapter(categories);
lv.setAdapter(categoryAdapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (position == 0){
categories = category_a;
categoryAdapter.notifyDataSetChanged();
}
}
});
}
private class CategoryAdapter extends ArrayAdapter<String>{
CategoryAdapter(String[] objects) {
super(getBaseContext(), R.layout.activity_categories,R.id.tvCategory, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = super.getView(position, convertView, parent);
return convertView;
}
}
}
please try this part of code inside your code if you want to update respected item only, make sure category_a has equal items
Version 1
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
categoryAdapter.insert(position,category_a[position]);
categoryAdapter.notifyDataSetChanged();
}
Version 2
if you want to update whole listview with all items in category_a then
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
categoryAdapter.clear();
categoryAdapter.addAll(category_a);
categoryAdapter.notifyDataSetChanged();
}

Eclipse: Tree View And Table View

I want to know if it's possible to use the same content and label providers for Tree and Table in Eclipse views or they must have separate content and label providers. I am trying to use the content and label providers i wrote for the tree for the table as well but i see nothing on the table view.
Thanks.
You CAN use the same Label provider.
You CAN'T use the same content provider since the tree content provider must implement ITreeContentProvider which is not "compatible" with the IStructuredContentProvider interface that must be implemented by table content provider.
By not "compatible" I mean that the implementation of IStructuredContentProvider.getElements(Object inputElement) method in TreeContentProvider must return only the "roots" objects whereas it must return all the objects for a list content provider.
You can share the providers. Your ContentProvider will have to implement both IStructuredContentProvider and ITreeContentProvider. I guess that normally you will want to have separate content providers.
In the example the Tree will show only one level with the elements (all elements are roots). The Table will show only one row.
Example:
//ContentProvider for Tree and Table
public static class CommonContentProvider extends ArrayContentProvider
implements ITreeContentProvider {
#Override
public Object[] getChildren(final Object arg0) {
return null;
}
#Override
public Object getParent(final Object arg0) {
return null;
}
#Override
public boolean hasChildren(final Object arg0) {
return false;
}
}
public static void testCommonProviderTreeTable(final Composite c) {
final Collection<String> input = Arrays.asList(new String[] { "hi",
"hola" });
final IContentProvider contentProvider = new CommonContentProvider();
final IBaseLabelProvider labelProvider = new LabelProvider() {
#Override
public String getText(final Object element) {
return element.toString();
}
};
final TreeViewer tree = new TreeViewer(c, SWT.NONE);
tree.setContentProvider(contentProvider);
tree.setLabelProvider(labelProvider);
tree.setInput(input);
final TableViewer table = new TableViewer(c, SWT.NONE);
table.setContentProvider(contentProvider);
table.setLabelProvider(labelProvider);
table.setInput(input);
}