Why my fragment does not work - java

I have a ListView in one side and a fragment on the other side. I am trying to make a simple app to figure out how fragments works.
Here is my code:
Main Activity:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// storing string resources into Array
//
setContentView(R.layout.activity_main);
String[] adobe_products = getResources().getStringArray(R.array.adobe_products);
//List view
final ListView list = (ListView)findViewById(R.id.questionsList);
ArrayAdapter<String> adapter;
adapter = new ArrayAdapter<String>(this, R.layout.list_item, adobe_products);
//final TextView text = (TextView)findViewById(R.id.textView1);
list.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
//String selectedFromList =(String) (list.getItemAtPosition(position));
//text.setText(selectedFromList);
}
});
list.setAdapter(adapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#SuppressLint("ValidFragment")
public class MyFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.activity_fragment, container, false);
}
}
}
Main Activity XML Layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >
<ListView
android:id="#+id/questionsList"
android:layout_width="144dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_weight="0.07" >
</ListView>
<fragment android:name="com.example.Layout.MyFragment"
android:id="#+id/article_fragment"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
UPDATE: Thanks for your help, I noticed that the fragment is a subclass so I included it inside my activity. But still getting the same result. it stops and doesn't even open. Anyway I updated the whole code that logCat.
LogCat:
02-22 00:06:50.944: E/AndroidRuntime(2886): FATAL EXCEPTION: main
02-22 00:06:50.944: E/AndroidRuntime(2886): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.layout/com.example.layout.MainActivity}: android.view.InflateException: Binary XML file line #21: Error inflating class fragment
02-22 00:06:50.944: E/AndroidRuntime(2886): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
02-22 00:06:50.944: E/AndroidRuntime(2886): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
02-22 00:06:50.944: E/AndroidRuntime(2886): at android.app.ActivityThread.access$600(ActivityThread.java:141)
Any idea to make it working?

I would recommend you to go through http://developer.android.com/guide/components/fragments.html and http://developer.android.com/training/basics/fragments/creating.html
I found many structural and Design problem in your Code , once you go through the above link you will understand it , also download the sample app available on above link page , if still you are not able to do I will surely try to give explanation with sample code. Good luck
Make the following changes in your code
1.add the fragment in activity layout like below and don't forget to replace YOUR PACKAGE NAME specified in class attribute
<fragment
android:id="#+id/article_fragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
class="YOUR PACKAGE NAME.MyFragment" />
2. Create MyFragment as a separate Class (Should not be inside the Main Activity):
3. Main Activity must extends FragmentAcivity instead of Actvity
4. if you need Listview and fragment side by side change LinearLayout Orientation to android:orientation="horizontal"
It will work

Hey u forgot to set the orientation for linear layout. By default its horizontal so just add the orientation attribute .
<LinearLayout
android:orientation="vertical" >
</LinearLayout>
in ur linear layout tag.
for the error inflating class fragment just change
import android.app.Fragment;
to: import android.support.v4.app.Fragment;
use onCreateView() to set layout for fragment -
The system calls this when it's time for the fragment to draw its user interface for the first time. To draw a UI for your fragment, you must return a View from this method that is the root of your fragment's layout. You can return null if the fragment does not provide a UI.

Related

Android: multiple fragments within a constraint layout

In advance, thank you for taking a few moments to read through this question and point out what is most likely an obvious mistake in my code. I've done some research and can't find a similar question- so here it is.
I am trying to create an android screen that shows 3 fragments separated on the screen like this- (first fragment in upper left as a search fragment, second (beneath it as a recycler layout) and the third detail fragment which inflates once an object is clicked on from the recycler list.
Page layout example:
I've accomplished this using a linear layout with two fragment containers with layout_weights, so when the search button is clicked in the first fragment, the recycler list takes the spot of the search fragment, and once clicked on inflates the detail container on the right, but again ideally id like all three fragments to be on the screen at the same time.
Here's the XML test layout that'd like to use:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/fragmentTest1"
android:name="com.swimlabs.pcms.progressionapp.SearchFragment"
android:layout_width="319dp"
android:layout_height="179dp"
android:layout_marginEnd="2dp"
app:layout_constraintBottom_toTopOf="#+id/divider"
app:layout_constraintEnd_toStartOf="#+id/divider2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/divider"
android:layout_width="325dp"
android:layout_height="14dp"
android:layout_marginEnd="2dp"
android:layout_marginTop="200dp"
android:background="?android:attr/listDivider"
app:layout_constraintEnd_toStartOf="#+id/divider2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/divider2"
android:layout_width="14dp"
android:layout_height="711dp"
android:layout_marginEnd="938dp"
android:background="?android:attr/listDivider"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/fragmentTest1"
app:layout_constraintTop_toTopOf="parent" />
<fragment
android:id="#+id/fragmentTest2"
android:name="com.swimlabs.pcms.progressionapp.SwimmerListFragment"
android:layout_width="270dp"
android:layout_height="424dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="2dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/divider2"
app:layout_constraintStart_toStartOf="parent" />
<fragment
android:id="#+id/fragment5"
android:name="com.swimlabs.pcms.progressionapp.ProgressionFragment"
android:layout_width="923dp"
android:layout_height="640dp"
android:layout_marginBottom="7dp"
android:layout_marginEnd="9dp"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/divider2" />
</android.support.constraint.ConstraintLayout>
Here are code excerpts how I am dynamically creating the fragments. Here is my singleton fragment class. What's commented out here is my old code which worked for with the linear layout with 2 containers.
public abstract class SingleFragmentActivity extends AppCompatActivity {
protected abstract Fragment createFragment();
#LayoutRes
protected int getLayoutResId() {
// return R.layout.master_coach;
return R.layout.test;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResId());
FragmentManager fm = getSupportFragmentManager();
// Fragment fragment = fm.findFragmentById(R.id.fragment_container);
Fragment fragment = fm.findFragmentById(R.id.fragmentTest1);
if (fragment == null) {
fragment = createFragment();
fm.beginTransaction()
// .add(R.id.fragment_container, fragment)
.add(R.id.fragmentTest1, fragment)
.commit();
}
}
}
Here is the onClick method from within the search fragment. I've tried overriding the onCreateView method from the SwimmerListActivity, and also tried playing with the fragment manager, but none of this works.
mSearchButton.setOnClickListener(new View.OnClickListener () {
#Override
public void onClick(View v) {
// Fragment fragment = SwimmerListFragment.newInstance();
// FragmentManager fm =
// getActivity().getSupportFragmentManager();
// fm.beginTransaction()
// .add(R.id.fragmentTest2, fragment)
// .commit();
Intent intent = new Intent(getActivity(),
SwimmerListActivity.class);
startActivity(intent);
}
});
I keep getting an error like this:
08-13 19:04:59.291 21931-21931/com.swimlabs.pcms.progressionapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.swimlabs.pcms.progressionapp, PID: 21931
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.swimlabs.pcms.progressionapp/com.swimlabs.pcms.progressionapp.CoachActivity}: android.view.InflateException: Binary XML file line #41: Binary XML file line #41: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
Where line 41 is the test.xml line where the second fragment begins.
If you can't tell I'm very new to this but I appreciate any resources or even general advice from you guys that can point me in the right direction to fix this. I don't expect anyone here to write my code for me. Thanks, please let me know if I can include any other information.
If you have to replace one fragment to another use .replace instead .add...ignore if that is not the case, sorry cant post an comment
It is easy these days. You can easily inflate fragments over constraint layout where ever you want to.
In .xml file, state three different constraint layout with IDs (No fragment View as stated above), constraint1,constraint2,constraint3. The design can be as you prefer.
Then use code like this for inflating fragments over these constraints:
FragmentTransaction fragmentTransaction=getSupportFragmentManager().beginTransaction();
Fragment fragment=new YourFragment1();
fragmentTransaction.replace(R.id.constraint1,fragment,null).commit();
Change your fragment name and respective constraint you want to inflate those fragment.

Binary XML Inflate Error on PopupMenu.show() Android

I'm trying to inflate a simple PopupMenu for rename/delete options when a RecylerView item is longClicked. For some reason i'm getting an XML inflate error when I call mPopup.show() after loading my xml file into the inflater.
I use similar logic elsewhere in my app to make a PopupMenu and it works fine. I've even tried loading the working PopupMenu from an unrelated part of the app into this inflater and I see the same android.view.InflateException: Binary XML file line #17: Failed to resolve attribute at index 1 error in logcat, so maybe the XML file isn't the problem?
How can I get this PopupMenu to inflate and show itself?
Fatal Exception Logcat
05-31 23:02:27.421 19597-20019/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.foo, PID: 19597
android.view.InflateException: Binary XML file line #17: Failed to resolve attribute at index 1: TypedValue{t=0x2/d=0x7f01005d a=-1}
Caused by: java.lang.UnsupportedOperationException: Failed to resolve attribute at index 1: TypedValue{t=0x2/d=0x7f01005d a=-1}
at android.content.res.TypedArray.getLayoutDimension(TypedArray.java:761)
at android.view.ViewGroup$LayoutParams.setBaseAttributes(ViewGroup.java:7060)
at android.view.ViewGroup$MarginLayoutParams.<init>(ViewGroup.java:7241)
at android.widget.FrameLayout$LayoutParams.<init>(FrameLayout.java:438)
at android.widget.FrameLayout.generateLayoutParams(FrameLayout.java:370)
at android.widget.FrameLayout.generateLayoutParams(FrameLayout.java:369)
at android.view.LayoutInflater.inflate(LayoutInflater.java:505)
at android.view.LayoutInflater.inflate(LayoutInflater.java:426)
at android.support.v7.view.menu.MenuAdapter.getView(MenuAdapter.java:93)
at android.support.v7.view.menu.MenuPopup.measureIndividualMenuWidth(MenuPopup.java:160)
at android.support.v7.view.menu.StandardMenuPopup.tryShow(StandardMenuPopup.java:153)
at android.support.v7.view.menu.StandardMenuPopup.show(StandardMenuPopup.java:187)
at android.support.v7.view.menu.MenuPopupHelper.showPopup(MenuPopupHelper.java:290)
at android.support.v7.view.menu.MenuPopupHelper.tryShow(MenuPopupHelper.java:175)
at android.support.v7.view.menu.MenuPopupHelper.show(MenuPopupHelper.java:141)
at android.support.v7.widget.PopupMenu.show(PopupMenu.java:233)
at com.example.foo.FragmentChordMenu.showChordOptionsMenu(FragmentChordMenu.java:132)
at com.example.foo.CustomChordAdapter$ChordViewHolder$2.onLongClick(CustomChordAdapter.java:138)
at android.view.View.performLongClickInternal(View.java:5687)
at android.view.View.performLongClick(View.java:5645)
at android.view.View.performLongClick(View.java:5663)
at android.view.View$CheckForLongPress.run(View.java:22234)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
FragmentActivity
public class FragmentChordMenu extends Fragment implements CustomChordAdapter.onItemClickListener {
private static RecyclerView mCustomChordList;
private static CustomChordAdapter mRecyclerViewAdapter;
private static Context mContext;
private FloatingActionButton mFAB;
private View mPopupView;
private PopupWindow mCustomChordMenu;
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mRecyclerViewAdapter = new CustomChordAdapter(this);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
mContext = getActivity().getApplicationContext(); //stores application context for later use in fragment without risk
//of detachment
View v = inflater.inflate(R.layout.menu_fragment_chord, container, false);
LayoutInflater layoutInflater = (LayoutInflater)getActivity().getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
...
mFAB = (FloatingActionButton) v.findViewById(R.id.addChord);
mFAB.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mCustomChordMenu.showAtLocation(mPopupView, Gravity.CENTER, 10, 10);
mCustomChordList = (RecyclerView) mPopupView.findViewById(R.id.rv_userChords);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
mCustomChordList.setLayoutManager(layoutManager);
mCustomChordList.setAdapter(mRecyclerViewAdapter);
}
});
return v;
}
public static void showChordOptionsMenu(final int position){
View anchorView = mCustomChordList.findViewHolderForAdapterPosition(position).itemView;
PopupMenu mPopup = new PopupMenu(mContext, anchorView);
mPopup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
case R.id.delete:
mRecyclerViewAdapter.deleteChord(position);
return true;
case R.id.rename:
Log.d("FragmentChordMenu: ", "Rename clicked");
}
return true;
}
});
MenuInflater popupInflater = mPopup.getMenuInflater();
popupInflater.inflate(R.menu.popup_delete_chord, mPopup.getMenu());
mPopup.show(); //ERROR HERE
}
...
}
PopupMenu XML
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<item
android:id="#+id/rename"
android:title="#string/rename"/>
<item
android:id="#+id/delete"
android:title="#string/delete"/>
</menu>
FragmentActivity XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android.support.design="http://schemas.android.com/tools"
android:id="#+id/chordMenu"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="#+id/scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/chordButtons"
android:orientation="vertical" >
</LinearLayout>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="16dp"
android:clickable="true"
app:fabSize="mini"
android:id="#+id/addChord"
app:borderWidth="0dp"
app:useCompatPadding="false"
android:src="#drawable/ic_add_black_24dp"/>
</LinearLayout>
</ScrollView>
</RelativeLayout>
The cause of the immediate issue here - the InflateException - was using the application Context for an appcompat-v7 PopupMenu.
mContext = getActivity().getApplicationContext();
...
PopupMenu mPopup = new PopupMenu(mContext, anchorView);
That Context won't have the correct theme resources set for a v7 widget, leading to the InflateException. The Activity does have the appropriate theme, though, and using that instead solves that particular issue.
mContext = getActivity();
After fixing that, however, a WindowManager$BadTokenException came up due to the PopupMenu being passed an anchor View from a PopupWindow. Popups must be anchored to a View in a top-level Window, and the Popup* classes are basically simple Views, thus the Exception.
A simple solution for this is to replace the PopupWindow with a Dialog, which does have a Window. For example:
AlertDialog dlg = new AlertDialog.Builder(getActivity()).setView(mPopupView).show();
Lastly, I would suggest that you modify your setup to remove the need for the static members in your Fragment class. Those static fields are likely to cause memory leaks, and your IDE may very well be warning you of that now. A listener interface similar to the one you have in CustomChordAdapter would suffice.

Fragment Intermediate(I):Getting input from edittext, set text in textview of a fragment

really in need of some advice, dont know what is wrong here.
Context:
2 fragments with a Textview each and the main activity has 2 button and a edittext
Aim:
Type hello into the edittext box in the main activity and
When click on the button for fragment 1, the textview will change to hello.
Problem:
Face a runtime error when enter hello into edittext and click on button 1.
Logcat:
E/AndroidRuntime(1291): FATAL EXCEPTION: main
E/AndroidRuntime(1291): android.view.InflateException: Binary XML file line #29: Error inflating class fragment
E/AndroidRuntime(1291): android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
E/AndroidRuntime(1291):android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
E/AndroidRuntime(1291):android.view.LayoutInflater.inflate(LayoutInflater.java:489)
E/AndroidRuntime(1291): android.view.LayoutInflater.inflate(LayoutInflater.java:396)
E/AndroidRuntime(1291): com.example.FragmentOne.onCreateView(FragmentOne.java:19)
E/AndroidRuntime(1291):android.app.FragmentManagerImpl.moveToState(FragmentManager.java:829)
fragment_one.xml
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#00ffff">
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="This is fragment No.1"
android:textStyle="bold" />
</LinearLayout>
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="#+id/easy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" >
<requestFocus />
</EditText>
<Button
android:id="#+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="selectFrag"
android:text="Fragment No 1" />
<Button
android:id="#+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="selectFrag"
android:text="Fragment No 2" />
<fragment
android:name="com.example.FragmentTwo"
android:id="#+id/fragment_place"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void selectFrag(View view) {
Fragment fr;
if(view == findViewById(R.id.button2)) {
fr = new FragmentTwo();
}else {
fr = new FragmentOne();
}
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.fragment_place, fr);
fragmentTransaction.commit();
}
}
FragmentOne.java
public class FragmentOne extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_one, container, false);
TextView monthlypayment= (TextView) view.findViewById(R.id.textView1);
EditText easy = (EditText) inflater.inflate(R.layout.activity_main, container, false).findViewById(R.id.easy);
monthlypayment.setText(easy.getText().toString());
return view;
}
}
There are two ways you can add a fragment to the activity layout:
Declare the fragment inside the activity's layout file.
Programmatically add the fragment to an existing ViewGroup.
Both methods are mentioned in the docs
http://developer.android.com/guide/components/fragments.html
If you want add the fragment to a container you need to use a ViewGroup in xml. Generally FrameLayout is used. So have the below in xml
<FrameLayout
android:id="#+id/fragment_place"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
The Activity code is fine. On Button click you replace the appropriate fragment in the container.
In your Fragment onCreateView you inflate the fragment layout and use the view object to initialize views of that layout. But you inflate activity_main.xml which is not required.
Quoting docs
Specifically, the fragment can access the Activity instance with
getActivity() and easily perform tasks such as find a view in the
activity layout
So for EditText you can use
EditText easy = (EditText)getActivity().findViewById(R.id.easy);
Or Initialize EditText in Activity on Button click get the value from EditTextand then you can pass the value of EditText from Activity to Fragment
Send data from activity to fragment in android
show me the onclick method, and the container u have fragment one in... its one of two things,
either you are programmatically adding a view which already exists, or you are tryin to update the ui without a handler.... handlers can be worked around in fragments, so im assuming its the first one....

Android fragment show as dialogfragment or usual fragment

What I am trying to achieve is to have a fragment that on tablet it shows as a DialogFragment, while on smartphone it would be shown as a regular fragment. I am aware there is already a similar post, but I am not able to make that work - apply the style to fragment.
To show things top down, MainActivity.java:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_next) {
decideToNext();
return true;
}
return super.onOptionsItemSelected(item);
}
private void decideToNext() {
String device = getString(R.string.device);
if ("normal".equalsIgnoreCase(device)) {
Intent intent = new Intent(this, DetailedActivity.class);
startActivity(intent);
} else if ("large".equalsIgnoreCase(device)) {
Log.d("SOME_TAG", "Yes, I am seeing this line on tablet only");
DetailedFragment fragment = DetailedFragment.newInstance();
getSupportFragmentManager().beginTransaction().add(fragment, "MAGIC_TAG").commit();
}
}
}
DetailedActivity is nothing much:
public class DetailedActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detailed_activity);
}
}
its layout:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_container"
android:name="com.myapps.sampleandroid.DetailedFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
and the interesting DetailedFragment:
public class DetailedFragment extends Fragment {
public static DetailedFragment newInstance() {
return new DetailedFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Context contextThemeWrapper = new ContextThemeWrapper(getActivity(), R.style.MyDialogTheme);
LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);
return localInflater.inflate(R.layout.detailed_fragment, container, false);
}
}
... and its layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Regular Text" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button Dummy" />
</LinearLayout>
In onCreateView I've tried to set the custom styling but it doesn't seem to work for tablet.
Styling
res/values/styles.xml contains:
<resources>
<style name="AppTheme" parent="#style/Theme.AppCompat.Light.DarkActionBar">
</style>
<style name="MyDialogTheme" />
</resources>
while res/values-large/styles.xml:
<resources>
<!-- Is there anything I should add here? -->
<style name="MyDialogTheme" parent="#android:style/Theme.Dialog"/>
</resources>
I've nested MyDialogTheme from Theme.Dialog, but it doesn't seem to help.
On smartphone when tapping on "NEXT" action bar menu item I am seeing the detailed activity (snapshot from an SG2):
while tapping on the same "NEXT" menu item from the tablet it doesn't do anything (except viewing the message on Logcat: Yes, I am seeing this line).
What should I add more in styles.xml or in code in order to see DetailedFragment as a dialog for tablet?
EDIT
I've tried the solution Little Child proposed (to have a DialogFragment contain my initial fragment and show it). So, I've added a WrapperDetailedFragment:
public class WraperDetailedFragment extends DialogFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.wrap_detailed_fragment, container, false);
}
}
its layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_container_dialog"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<fragment
android:id="#+id/wrapped_fragment_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.myapps.sampleandroid.DetailedFragment" />
</LinearLayout>
The code from MainActivity changes to:
private void decideToNext() {
String device = getString(R.string.device);
if ("normal".equalsIgnoreCase(device)) {
Intent intent = new Intent(this, DetailedActivity.class);
startActivity(intent);
} else if ("large".equalsIgnoreCase(device)) {
Log.d("SOME_TAG", "Yes, I am seeing this line ...");
WraperDetailedFragment fragment = new WraperDetailedFragment();
fragment.show(getSupportFragmentManager(), "MAGICAL_TAG");
}
}
but when I'm trying to add this DialogFragment I am getting the following crash:
android.view.InflateException: Binary XML file line #8: Error inflating class fragment
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at com.myapps.sampleandroid.WraperDetailedFragment.onCreateView(WraperDetailedFragment.java:12)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1478)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:927)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1082)
at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:304)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:676)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at com.myapps.sampleandroid.WraperDetailedFragment.onCreateView(WraperDetailedFragment.java:12)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1478)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:927)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalArgumentException: Binary XML file line #8: Duplicate id 0x7f050047, tag null, or parent id 0x0 with another fragment for com.myapps.sampleandroid.DetailedFragment
at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:290)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:676)
... 28 more
This issue can be easily fixed if instead of trying to make a Fragment look like a DialogFragment I would look from the opposite angle: make a DialogFragment look like a Fragment - after all, a DialogFragment is a Fragment!
The key of this fix is to call or not DialogFragment.setShowsDialog();
So changing the DetailedFragment to:
public class DetailedFragment extends DialogFragment {
private static final String ARG_SHOW_AS_DIALOG = "DetailedFragment.ARG_SHOW_AS_DIALOG";
public static DetailedFragment newInstance(boolean showAsDialog) {
DetailedFragment fragment = new DetailedFragment();
Bundle args = new Bundle();
args.putBoolean(ARG_SHOW_AS_DIALOG, showAsDialog);
fragment.setArguments(args);
return fragment;
}
public static DetailedFragment newInstance() {
return newInstance(true);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
setShowsDialog(args.getBoolean(ARG_SHOW_AS_DIALOG, true));
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.detailed_fragment, container, false);
}
}
its layout remains as it was, DetailedActivity changes to:
public class DetailedActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detailed_activity);
if (savedInstanceState == null) {
DetailedFragment fragment = DetailedFragment.newInstance(false);
getSupportFragmentManager().beginTransaction().add(R.id.root_layout_details, fragment, "Some_tag").commit();
}
}
}
its layout as well:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_layout_details"
android:layout_width="match_parent"
android:layout_height="match_parent" />
and the caller activity does only:
private void decideToNext() {
String device = getString(R.string.device);
if ("normal".equalsIgnoreCase(device)) {
Intent intent = new Intent(this, DetailedActivity.class);
startActivity(intent);
} else if ("large".equalsIgnoreCase(device)) {
DetailedFragment fragment = DetailedFragment.newInstance();
fragment.show(getSupportFragmentManager(), "Tablet_specific");
}
}
To make a DialogFragment show as a regular Fragment, call add() or replace() using a resource ID for the fragment container, e.g
beginTransaction().add(R.id.fragment_container, fragment)
But to make the DialogFragment display as a dialog, call add(fragment, "Fragment Tag"). Behind the scenes this results in a call to add(resId, fragment), setting the resource ID for the fragment container to 0, which causes the DialogFragment to set its showAsDialog option to true.
As a consequence you can use a dialog fragment as a dialog or a regular fragment - depending on your needs - without needing to create any special logic to do it.
OK, I have been there and done that. To make a DialogFragment you need a layout defined in XML. Say, for this you have LinearLayout as root. In this LinearLayout you can add a fragment class="...." and when you display your DialogFragment, it will be the same Fragment you displayed side by side on the tablet now displayed in a DialogFragment.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
<fragment class="com.example.tqafragments.FeedFragment" android:id="#+id/feedFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1"/>
</LinearLayout>
Like so. And inflate this in your DialogFragment

How do I populate a ListFragment in Android?

I have seen all kinds of tutorials about how to turn an Activity into a ListActivity to populate a ListView, but nothing for ListFragments. I have two tabs with a Fragment under each. Here is what my fragment currently looks like.... can someone give me some idea on how I can do this?
public class MainFragment extends ListFragment {
String[] items = { "12 Monkeys", "(500) Days of Summer", "Chariots of Fire" };
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
return inflater.inflate(R.layout.fragment_main, container, false);
}
}
and here is the XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
I'm trying to get items to show in the ListView.
You don't need to inflate a view containing a listview inside of your ListFragment. Simply create an adapter, give it some data and in onCreate() of your fragment call setListAdapter(). Then somewhere else (presumably in your Activity) you can then add this fragment with a fragmentmanager.

Categories