Fragment not displayed - android

I am having an activity which has a list view which uses a list adapter to display elements. When the element which has text is clicked on the fragment should be created which has the play button, seek bar and has a media player. However I get this error when my activity is called.
The line 14 is the list_songs is the one which has
"fragment" beginning tag
> 02-26 02:01:27.625: E/AndroidRuntime(2419): FATAL EXCEPTION: main
> 02-26 02:01:27.625: E/AndroidRuntime(2419):
> java.lang.RuntimeException: Unable to start activity
> ComponentInfo{com.songs/com.songs.display.DisplaysongDetails}:
> android.view.InflateException: Binary XML file line #14: Error
> inflating class fragment
The code for the activity is
public class DisplaysongDetails extends ListActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.list_songs);
setListAdapter(new ArrayAdapter<String>(this, R.layout.row,songDetails));
ListView listView = (ListView) this.findViewById(android.R.id.list);//getListView();
listView.setTextFilterEnabled(true);
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String name = ((TextView) view).getText().toString();
if (name=="Play")
{
PlayerFragment frag = (PlayerFragment) getFragmentManager().findFragmentById(R.id.player_fragment);
if (frag == null) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.player_fragment, new PlayerFragment());
ft.commit();
}}
}
});
}}
list_songs.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFFFF">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<fragment
android:id="#+id/player_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.songs.PlayerFragment" />
</LinearLayout>
The fragment class is:
public class PlayerFragment extends Fragment implements OnTouchListener, OnCompletionListener, OnBufferingUpdateListener{
private Button btn_play;
private SeekBar seekBar;
private MediaPlayer mediaPlayer;
private int lengthOfAudio;
private int length=0;
String URL = (new AppConfig()).getURL();
private final String url = URL + "/play/song.mp3";
private final Handler handler = new Handler();
private final Runnable r = new Runnable() {
public void run() {
updateSeekProgress();
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#SuppressLint("NewApi")
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.player_fragment, container, false);
btn_play = (Button) view.findViewById(R.id.btn_play);
btn_play.setOnClickListener(new OnClickListener());
seekBar = (SeekBar)getActivity().findViewById(R.id.seekBar);
seekBar.setOnTouchListener(this);
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnCompletionListener(this);
return view;
}}
Fragment XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<SeekBar
android:id="#+id/seekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="3dp" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:gravity="center_horizontal"
android:orientation="horizontal" >
<Button
android:id="#+id/btn_play"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:text="play" />
</LinearLayout>
</LinearLayout>

First, you have given fill_parent for both width and height of your ListView which makes your ListView occupy the whole parent(here LinearLayout), so no place for Fragment. Its good that you have null check in your code if (frag == null), but again you are trying to add your fragment to the same View which is not in the screen(not attached).
Perhaps you would want to start a new activity if you found that your Fragment is not attached to your view hierarchy.
if (frag == null) {
Intent playerActivity = new Intent(DisplaysongDetails.this, PlayerActivity.class)
startActivity(playerActivity);
}
Now, create a new Activity called PlayerActivity and add PlayerFragment in its layout. You can pass any item data using Extras.

Another issue:
seekBar = (SeekBar)getActivity().findViewById(R.id.seekBar);
seekBar.setOnTouchListener(this);
seekBar is only defined as part of the Fragment layout, not the Activity's. That call to getActivity().findViewById() should return null and result in an NPE when trying to add the Listener. However, more info (from the stack trace) is needed to see if anything else is wrong (besides this and the String comparison).
What would be valid:
seekBar = (SeekBar)view.findViewById(R.id.seekBar);
seekBar.setOnTouchListener(this);

Related

Trying to add selected image views by(OnItemClickListener), between fragments, on the second ImageView the app crashes

I'm trying to add and show a multiple image views existing in a fragment to another in the same activity by OnItemClickListener on GridView.
I was able to add the first image view but when I add the second one the app crashes.
By the way, I'm adding the image views to a linear layout inside Horizontal Scroll View.
Here is the layout of the first fragment:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/content_fragment_id"
>
<GridView
android:id="#+id/items_id_gridView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:columnWidth="100dp"
android:minHeight="40dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:numColumns="auto_fit"
android:horizontalSpacing="10.0dip"
android:verticalSpacing="10.0dip"
android:cacheColorHint="#00000000"
android:gravity="center_horizontal"
android:requiresFadingEdge="vertical"
/>
</RelativeLayout>
The layout of the second fragment:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<ImageButton
android:id="#+id/play_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/play_36dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:contentDescription="#string/play_button" />
<HorizontalScrollView
android:id="#+id/sentenceBarScrollView"
android:layout_width="fill_parent"
android:layout_height="104dp"
android:layout_toLeftOf="#id/play_button"
android:layout_toStartOf="#id/play_button"
android:padding="1dp"
>
<LinearLayout
android:id="#+id/sentence_bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="2dp"
android:orientation="horizontal"
>
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
The layout of the main activity:
<android.support.constraint.ConstraintLayout
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"
tools:context=".Home"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
android:id="#+id/sentence_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="vertical">
<fragment
android:id="#+id/sentenceBarFragment"
android:name="ye.com.ebra.contentfragments.SentenceBarFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
</android.support.v7.widget.CardView>
<RelativeLayout
android:id="#+id/content_Layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/sentence_layout"
android:padding="5dp"
>
<!-- put contents fragments here :) -->
</RelativeLayout>
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
the class of the first fragment.
sendItemToSentenceBar connector;
//for retrieving the values of the image stored in database
private Item item;
static ArrayList<Integer> back;
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
back=new ArrayList<>();
DBConnection dbConnection= new DBConnection(getActivity());
GridView gridView=getActivity().findViewById(R.id.items_id_gridView);
final ArrayList<Item> items2=new ArrayList<>(dbConnection.getAll(Cat_id));
ContentAdapter dataAdapter=new ContentAdapter(getActivity(),items2);
gridView.setAdapter(dataAdapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
item=items2.get(position);
if(item.getType().equals("Category"))
{
back.add(Cat_id);
changeFragment(item.getID());
AddNewDialogFragment.Cat_id=item.getID();
}else {
speak(item.getName());
connector.sendData(item);
}
}
});
}
and I'm using an interface to pass the data from OnItemClickListener to the other fragment by "connector.sendData(item);"
Here is the interface:
public interface sendItemToSentenceBar {
// send item to the sentence bar fragment :)
void sendData(Item item);
}
Then in the class of the other fragment
There is the method AddItem(Item item) that should add the image view to the second fragment, the first image view can be added be on the second one the app just crashes :
private ArrayList<Item> items;
private LinearLayout sentenceLayout;
private View itemView;
private ArrayList<View> itemsViews;
View view;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View sentenceBarFragment=inflater.inflate(R.layout.activity_sentence_bar_fragment,container,false);
sentenceLayout = sentenceBarFragment.findViewById(R.id.sentence_bar);
itemView = inflater.inflate(R.layout.activity_item,sentenceLayout,false);
return sentenceBarFragment;
}
public void AddItem(Item item){
TextView name_id = itemView.findViewById(R.id.name_id);
name_id.setText(item.getName());
ImageView image_id = itemView.findViewById(R.id.image_id);
image_id.setImageBitmap(convertByteToBitmap(item.getImage()));
itemsViews.add(itemView);
sentenceLayout.addView(itemsViews.get(0));
items.add(item);
}
Finally the method AddItem(Item item) is used in the class of the main activity that contain both of the fragments:
#Override
public void sendData(Item item) {
FragmentManager fragmentManager=getFragmentManager();
SentenceBarFragment s= (SentenceBarFragment) fragmentManager.findFragmentById(R.id.sentenceBarFragment);
s.AddItem(item);
}
Here the Logcat:
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:3378)
at android.view.ViewGroup.addView(ViewGroup.java:3249)
at android.view.ViewGroup.addView(ViewGroup.java:3194)
at android.view.ViewGroup.addView(ViewGroup.java:3170)
at ye.com.ebra.contentfragments.SentenceBarFragment.AddItem(SentenceBarFragment.java:95)
at ye.com.ebra.contentfragments.Home.sendData(Home.java:129)
at ye.com.ebra.contentfragments.ContentFragment$2.onItemClick(ContentFragment.java:83)
at android.widget.AdapterView.performItemClick(AdapterView.java:298)
at android.widget.AbsListView.performItemClick(AbsListView.java:1086)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:2855)
at android.widget.AbsListView$1.run(AbsListView.java:3529)
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)
of the Logcat, I could identify those errors:
at ye.com.ebra.contentfragments.SentenceBarFragment.AddItem(SentenceBarFragment.java:95)
which is at the class of the second fragment, in the method AddItem(Item item)
sentenceLayout.addView(itemsViews.get(0));
.
at ye.com.ebra.contentfragments.Home.sendData(Home.java:129)
which is at the class of the main activity, in the used method
sendData(Item item)
s.AddItem(item);
.
at ye.com.ebra.contentfragments.ContentFragment$2.onItemClick(ContentFragment.java:83)
which is in the class of the first fragment, in OnItemClickListener:
connector.sendData(item);
Sorry for the long post, but I'm really stuck here
You appear to be repeatedly modifying and adding the same item_view object inflated in onCreateView(...) method. It strikes me that you need to inflate a new object each time you call "AddItem".
There is also a possible issue with appending views to the itemViews list but repeatedly adding the first view in the list (ie. not the one you just added) .
So SentenceBarFragment might look instead like this:
private ArrayList<Item> items;
private LinearLayout sentenceLayout;
private ArrayList<View> itemsViews;
#Nullable
#Override public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View sentenceBarFragment=inflater.inflate(R.layout.activity_sentence_bar_fragment,container,false);
sentenceLayout = sentenceBarFragment.findViewById(R.id.sentence_bar);
return sentenceBarFragment;
}
public void AddItem(Item item){
// inflate a new view to be added
View itemView = LayoutInflater.from(getActivity()).inflate(R.layout.activity_item,sentenceLayout,false);
TextView name_id = itemView.findViewById(R.id.name_id);
name_id.setText(item.getName());
ImageView image_id = itemView.findViewById(R.id.image_id);
image_id.setImageBitmap(convertByteToBitmap(item.getImage()));
// add the view you just inflated
itemsViews.add(itemView);
sentenceLayout.addView(itemView); // or addView(itemViews.get(itemViews.size()-1))
items.add(item);
}

Trouble editing TextView within Fragment

So I am still fairly new to working with Android Studio and everything in it. I have been stuck on trying to get fragments to communicate directly with each other. Here I'm simply just trying to set the TextView text element within one of my fragments. I have looked for hours and tried a lot, but I'm not sure what to do. Also, I am implementing my fragments through code in a FrameLayout.
Here is my fragment whose text value I'm trying to edit:
public class ReceivingFrag extends Fragment {
TextView sender;
public void updateText(String text) {
sender.setText(text);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.frag_sender, container, false);
sender = (TextView) v.findViewById(R.id.sender);
return v;
}
}
I believe my root problem is that getView() and sender both return Null. I also understand that fragments are not technically views, but rather aid in the layout of views and ViewGroups. Any help is appreciated.
Not sure if it helps, but this is the method that calls the updateText() method within the ReceivingFrag class.
public void sendText(String text){
ReceivingFrag frag = new ReceivingFrag();
getSupportFragmentManager().beginTransaction().add(R.id.receiving_container, frag).commit();
getSupportFragmentManager().executePendingTransactions()
frag.updateText(text);
}
**Edit:
This is my MainActivity class that is calling and creating the Fragment:
public class MainActivity extends AppCompatActivity implements SendingFragment.TextClicked {
private static final String TAG = MainActivity.class.getSimpleName();
public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] myStringArray = {"Hello", "Nice To See You", "Bye"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, myStringArray);
ListView listView = (ListView) findViewById(R.id.mobile_list);
listView.setAdapter(adapter);
sendText("Hello");
}
#Override
public void sendText(String text){
ReceivingFrag frag = new ReceivingFrag();
getSupportFragmentManager().beginTransaction().add(R.id.receiving_container, frag).commit();
getSupportFragmentManager().executePendingTransactions();
frag.updateText(text);
}}
**Edit 2:
This is the MainActivity layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/apk/tools"
xmlns:tools2="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="1">
<EditText android:id="#+id/edit_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="#string/edit_message"
android:layout_weight="1" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="sendMessage"
android:text="#string/button_send"/>
</LinearLayout>
<ListView android:id="#+id/mobile_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="#+id/receiving_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></FrameLayout></LinearLayout>
And this is the layout for the Fragment:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/sender"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/frag_sender"
android:background="#color/gray"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"/></LinearLayout>
Solution:
So as mentioned below, the runtime error was fixed by adding
#Override
protected void onResume() {
super.onResume();
sendText("hello");
}
to the MainActivity class. After reading from https://developer.android.com/guide/components/fragments.html#Lifecycle
I think the statement
"Once the activity reaches the resumed state, you can freely add and remove fragments to the activity. Thus, only while the activity is in the resumed state can the lifecycle of a fragment change independently."
best explains the situation and why the error initially occurred.
If you instead put the sendText() in your onResume() like this,
#Override
protected void onResume() {
super.onResume();
sendText("Hello");
}
It will not give you the Null Pointer Exception. The fragment is still null when you call on it from onCreate().
Change your Fragment to this:
public class ReceivingFrag extends Fragment {
private TextView sender;
public void updateText(String text) {
sender.setText(text);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.frag_sender, container, false);
sender = (TextView) v.findViewById(R.id.sender);
return v;
}
}
and in your activity, before calling the updateText method, make sure the fragment transaction has executed by doing:
public void sendText(String text){
ReceivingFrag frag = new ReceivingFrag();
getSupportFragmentManager().beginTransaction().add(R.id.receiving_container, frag).commit();
getSupportFragmentManager().executePendingTransactions();
frag.updateText(text);
}

Why is the text of TextView not restored when setRetainInstance(true) has been called?

I called setRetainInstance(true) for a fragment. I added an EditText and TextView on the fragment. When rotated, the text in the EditText survived, but the text in the TextView was gone.
I think I can manually restore the text of the TextView, but I wonder why the system automatically restores the text for EditText, and not for TextView. Did I do something wrong?
Steps to reproduce.
Type "android" in the EditText
Press the [Test 1] button. The TextView now displays "android"
Rotate the device.
Result
The EditText has "android", but the TextView is empty.
MyFragment.java
public class MyFragment extends Fragment
{
private static final String TAG = "MyFragment";
EditText etInput;
Button btnTest1;
TextView tvMessage;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState)
{
Log.d(TAG, "onCreateView()");
View v= inflater.inflate(R.layout.my_fragment, container, false);
etInput = (EditText)v.findViewById(R.id.etInput);
btnTest1 = (Button)v.findViewById(R.id.btnTest1);
btnTest1.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
tvMessage.setText(etInput.getText().toString());
Log.d(TAG, "btnTest1 was clicked");
}
});
tvMessage = (TextView) v.findViewById(R.id.tvMessage);
return v;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity
{
String TAG = this.getClass().getName();
#Override
protected void onCreate(Bundle savedInstanceState)
{
Log.d(TAG, "onCreate()");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm = getSupportFragmentManager();
Fragment mf = fm.findFragmentById(R.id.placeholder);
if(mf == null)
{
Log.d(TAG, "creating new my fragment");
mf = new MyFragment();
mf.setRetainInstance(true);
fm.beginTransaction().add(R.id.placeholder, mf).commit();
}
}
}
my_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="#+id/etInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/tvMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="#+id/btnTest1"
android:text="Test 1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
activity_main.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"
>
<TextView
android:text="Fragment Test"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<FrameLayout
android:id="#+id/placeholder"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp">
</FrameLayout>
</LinearLayout>
If you want to enable auto restoration of TextView, you need to set freezesText attribute to true in your xml (or call setFreezesText(true)).
For TextView, freezesText default value is false, but in case of EditText, default value is true.
From documentation of freezesText:
If set, the text view will include its current complete text inside of
its frozen icicle in addition to meta-data such as the current cursor
position. By default this is disabled; it can be useful when the
contents of a text view is not stored in a persistent place such as a
content provider. For EditText it is always enabled, regardless of the
value of the attribute.

When declaring buttons different fragments does not recognize

I have a problem when declaring a button.
I will try to explain as specific as possible.
In my main Layout I have a Fragment containing a secondary Layout. In which I have several buttons.
My intention is that my main fichero.java to declare the buttons within the fragment.
Here we put the main Layout:
<RelativeLayout
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:baselineAligned="false">
<fragment
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:name="josejuansosarodriguez.radioecca.conocecanarias.TrueoFalseFragment"
android:id="#+id/fragmentTrueFalse"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/Grp1"
android:id="#+id/textGrp1"
android:textSize="25sp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"/>
<fragment
android:layout_width="fill_parent"
android:layout_height="450dp"
android:name="josejuansosarodriguez.radioecca.conocecanarias.Grp1FragmentP1"
android:id="#+id/fragmetaskGRP1"
android:layout_below="#+id/textGrp1"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp" />
</RelativeLayout>
Here we put the secondary Layout that has the buttons:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:id="#+id/fragment_TrueorFalse">
<Button
android:layout_width="120sp"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="#string/buttontrue"
android:id="#+id/buttontrue"
android:layout_marginLeft="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true" />
<Button
android:layout_width="120sp"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="#string/buttonfalse"
android:id="#+id/buttonfalse"
android:layout_marginRight="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true" />
</RelativeLayout>
And here I leave the my main activity:
public class Grp1Fragment extends Fragment {
private Button buttonTrue;
private Button buttonFalse;
private Button buttonNextAsk;
private View view;
public Grp1Fragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
buttonTrue = (Button) view.findViewById(R.id.buttontrue);
buttonTrue.setOnClickListener(this);
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_grp1, container, false);
return view;
}
My problem I find in the following line:
buttonTrue.setOnClickListener (this);
The message reads: View can not be in Applied to josejuansosarodriguez.radioecca.conocecanarias.Grp1Fragment
I hope I have spread far.
Thank you very much for everything, this forum is amazing.
Try this:
Note that you have to FIRST inflate the layout to make accesible the widgets of the layout.
Then you can "bind" the widgets, and finallly in this case, set the listeners to the buttons.
I set you a Log, if you need change it to Toast, or code
public class Grp1Fragment extends Fragment {
private Button buttonTrue;
private Button buttonFalse;
private Button buttonNextAsk;
private View view;
public Grp1Fragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_grp1, container, false);
//Declare your widgets (Buttons)
buttonTrue = (Button) view.findViewById(R.id.buttontrue);
buttonFalse = (Button) view.findViewById(R.id.buttonfalse);
//Set the Listeners
buttonTrue.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//Toast or Log, or whateber you need
Log.d("Fragment1" , "Button: True");
}
});
buttonFalse.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//Toast or Log, or whateber you need
Log.d("Fragment1" , "Button: FAlse");
}
});
//return the view
return view;
}
void setOnClickListener(View.OnClickListener l)
requires a OnClickListener, which Grp1Fragment is not.
Use something like
buttonTrue.setOnClickListener(new View.OnClickListener() {
void onClick(View v) {
... // reaction on the button
}
});

Replace activity content with static fragment

I have an app which is using an activity at the start. It is loading an xml-file to set the content at the onStart-procedure. After that the content is changed with a fragment which let the user make an input in an EditText view. This fragment is loaded dynamically at run time by using the FragmentManager and Transaction. Also on this fragment there is a Button to go on. When the user clicks the button another content is loaded at the onClick-procedure of that button. I tried to replace the first fragment with another one called “ListFrag.java” which is using a layout file called “list_frag.xml”. In portrait mode this new a simple xml-layout with some views on it.
The problem starts when the device is in landscape mode. I check this with “getResources().getConfiguration().orientation“. At this time I would like to change the start fragment “ListFrag.java” with another version of the layout “list_frag.xml”. Therefore I put this layout in a new res folder called “layout-land”. This layout defines a static fragment for the left pane and a frame-layout for the right pane. The frame-layout serves as a container for a detail fragmen to be loaded if the user clicked an item in the left pane.
I really do not know if it is possible to alter the content of an activity with a fragment on it using a layout with a static fragment definition in it. I tried already everything but nothing works. May be here someone has an idea.
Here are the source-code for the single files in the project. To shorten the code I removed the import-statements:
MainActivity:
package com.example.wbslideshow;
public class MainActivity extends Activity implements MainFrag.onstartFragBtnClickListener {
public static final String KEYVAL = "startpath";
Bundle mySavedInstanceState;
MainFrag newMainFrag;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mySavedInstanceState = savedInstanceState;
//initialize the preferences from the xml-file
//if app is running the first time this will be taken from the xml-file
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
//load the MainFrag to select a path to the images and start-button
newMainFrag = new MainFrag();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.add(R.id.mycontainer, newMainFrag);
transaction.addToBackStack(null);
transaction.commit();
}
//procedure from the interface of the MainFrag class to look for images in the given path
#Override
public void onstartFragBtnClicked(String root)
{
//call procedure "private boolean LandscapeMode()" to check the mode
if (!LandscapeMode())
{
ListFrag newListFrag = new ListFrag();
//put the value from the EditText field of MainFrag class into the arguments for the ListFrag class
Bundle args = new Bundle();
args.putString(ListFrag.FRAG_MESSAGE_DEF_Input, root);
newListFrag.setArguments(args);
//change the fragments dynamically
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.mycontainer, newListFrag);
transaction.addToBackStack(null);
transaction.commit();
}
else
{
//remove the MainFrag
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.remove(newMainFrag);
transaction.commit();
//load the static ListFrag
ListFrag newListFrag = new ListFrag();
//put the value from the EditText field of MainFrag class into the arguments for the ListFrag class
Bundle args = new Bundle();
args.putString(ListFrag.FRAG_MESSAGE_DEF_Input, root);
//load the ImgFrag for the right pane into the FrameLayout
ImgFrag myImgFrag = new ImgFrag();
if (myImgFrag != null)
{
transaction = getFragmentManager().beginTransaction();
transaction.add(R.id.myImgContainer, myImgFrag);
transaction.commit();
}
}
}
private boolean LandscapeMode() {
if (getResources().getConfiguration().orientation ==
Configuration.ORIENTATION_PORTRAIT) {
return false;
}
else
if (getResources().getConfiguration().orientation ==
Configuration.ORIENTATION_LANDSCAPE) {
return true;
} else return false;
}
}
MainFrag:
package com.example.wbslideshow;
public class MainFrag extends Fragment implements OnClickListener{ //, OnSharedPreferenceChangeListener {
/*
* Constant is representing the value of the android:key from preferences.xml.
* This value is found in android:defaultValue
*/
public static final String KEYVAL = "startpath";
public static final String JPGVAL = "pref-jpg";
public static final String PNGVAL = "pref-png";
EditText myEditText;
SharedPreferences sharedPref;
//define the interface to communicate with the main activity when user clicked the button
private onstartFragBtnClickListener mCallback;
public interface onstartFragBtnClickListener {
public void onstartFragBtnClicked(String myInput);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle SavedInstanceState ) {
View view = inflater.inflate(R.layout.main_frag, container, false);
//instantiate the start button and register the onClickListener
Button start = (Button) view.findViewById(R.id.startBtn);
start.setOnClickListener(this);
//read the current path to the pics from SharedPreferences file
Activity myActivity = getActivity();
sharedPref = PreferenceManager.getDefaultSharedPreferences(myActivity.getBaseContext());
//registerPreferenceListener();
myEditText = (EditText) view.findViewById(R.id.inputSearchPath);
myEditText.setText(sharedPref.getString(KEYVAL, "/"));
return view;
}
#Override
public void onResume() {
super.onResume();
//read the current path to the pics from SharedPreferences file
Activity myActivity = getActivity();
sharedPref = PreferenceManager.getDefaultSharedPreferences(myActivity.getBaseContext());
myEditText.setText(sharedPref.getString(KEYVAL, "/"));
}
#Override
public void onAttach (Activity activity) {
super.onAttach(activity);
try
{mCallback = (onstartFragBtnClickListener) activity;}
catch (ClassCastException e)
{throw new ClassCastException(activity.toString()
+ " must implement OnControlButtonClickedListener");}
}
//change to ListFrag class if user clicked the button
#Override
public void onClick(View view)
{
Activity myActivity = getActivity();
if (myActivity != null)
{
//Get the users input for to pass it to the activity
String root = ((EditText) myActivity.findViewById(
R.id.inputSearchPath)).getText().toString();
//Call the interface method in the activity to go on
mCallback.onstartFragBtnClicked(root);
}
}
}
ListFrag:
package com.example.wbslideshow;
public class ListFrag extends ListFragment{
ImageView image;
//Arrays to get files and folders
private List<String> listItem = null;
//TextView Object for the headline
private TextView TVmyPath;
//global variable taken the start path once
//used to compare when user clicked an item
private String g_startPath, g_myInput;
/* define a constant to take the passed input string from the start fragment */
public static String FRAG_MESSAGE_DEF_Input = "com.example.wbslideshow.CALL_ListFragment";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle SavedInstanceState ) {
View myview = inflater.inflate(R.layout.list_frag, container, false);
TVmyPath = (TextView) myview.findViewById(R.id.startpath);
return myview;
}
#Override
public void onStart()
{
super.onStart();
Activity myActivity = getActivity();
//get an instance of the image and make it invisible
image = (ImageView) myActivity.findViewById(R.id.imageView1);
image.setVisibility(View.INVISIBLE);
Bundle args = getArguments();
if (args != null) { g_startPath = args.getString(FRAG_MESSAGE_DEF_Input); }
//save the input the very first time to compare later with new item click
g_myInput = g_startPath;
getDir(g_startPath);
}
private void getDir(String p_startPath)
{
//set the headline
TVmyPath.setText("Location: " + p_startPath);
listItem = new ArrayList<String>();
File f = new File(p_startPath);
//file array which get's all the folders and files from the input path
File[] files = f.listFiles();
//startPath changed if user clicked a new folder
if(!g_myInput.equals(p_startPath))
{
//alter g_myInput for the next comparison
g_myInput = p_startPath;
//put this item to make it possible to get one directory up
listItem.add("../");
}
Arrays.sort(files, filecomparator);
for(int i=0; i < files.length; i++)
{
if(files[i].isFile())
{
String filename = files[i].getName();
//get the file extension
int z = filename.lastIndexOf('.');
//read the file extension
String wbname = filename.substring(z+1);
if (wbname.equalsIgnoreCase("jpg")) {listItem.add(filename);}
if (wbname.equalsIgnoreCase("jpeg")) {listItem.add(filename);}
}
else {listItem.add(files[i].getName() + "/");}
}
ArrayAdapter<String> fileList =
new ArrayAdapter<String>(getActivity(), R.layout.row, listItem);
Activity myActivity = getActivity();
ListView myList = (ListView) myActivity.findViewById(android.R.id.list);
myList.setAdapter(fileList);
}
//procedure to sort the arrays
Comparator<? super File> filecomparator = new Comparator<File>(){
public int compare(File file1, File file2) {
if(file1.isDirectory()){
if (file2.isDirectory()){
return String.valueOf
(file1.getName().toLowerCase(Locale.getDefault())).compareTo
(file2.getName().toLowerCase(Locale.getDefault()));
}else{
return -1;
}
}else {
if (file2.isDirectory()){
return 1;
}else{
return String.valueOf
(file1.getName().toLowerCase(Locale.getDefault())).compareTo
(file2.getName().toLowerCase(Locale.getDefault()));
}
}
}
};
#Override
public void onListItemClick(ListView l, View v, int position, long id)
{
File file;
//user clicked one path back
if (listItem.get(position) == "../")
{
file = new File(g_startPath);
g_startPath = file.getParent();
}
else
//if user clicked to a picture or
//to a new folder (>> getDir has to be called with the new path)
// >>file has to be set to path and position
{file = new File(g_startPath + '/' + listItem.get(position));}
Bitmap myBitmap;
//user clicked only to an image >> the image has to be shown in the image view - nothing else
if (file.isFile())
{
//if(file.canRead()){
myBitmap = BitmapFactory.decodeFile(file.getPath());
image.setImageBitmap(myBitmap);
image.setVisibility(View.VISIBLE);
//}
}else
{
if (file.isDirectory())
{
image.setVisibility(View.INVISIBLE);
if (listItem.get(position) != "../"){g_startPath = file.getPath();}
getDir(g_startPath);
}
}
}
}
ImgFrag:
package com.example.wbslideshow;
public class ImgFrag extends Fragment{
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View myImgView = inflater.inflate(R.layout.img_frag, container, false);
return myImgView;
}
}
The Layouts
activity_main.xml
<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:background="#DA8306"
android:orientation="vertical"
android:id="#+id/mycontainer">
</LinearLayout
main_frag.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/FragMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/startHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/startHeader" />
<EditText
android:id="#+id/inputSearchPath"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="#string/startInputHint" >
<requestFocus />
</EditText>
<Button
android:id="#+id/startBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/startBtn" />
</LinearLayout>
layout/list_frag.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:id="#+id/listFrag"
android:orientation="vertical" >
<TextView
android:id="#+id/startpath"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#C27302"
android:height="40dp"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="#string/list_header"
android:textSize="16sp"
android:textStyle="bold" />
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="312dp"
android:layout_gravity="fill"
android:background="#B012EB" />
<TextView
android:id="#+id/empty"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_ab_bottom_solid_dark_holo" />
<FrameLayout
android:id="#+id/myImgContainer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="fill_parent"
/>
</LinearLayout>
layout-land/list_frag.xml:
<?xml version="1.0" encoding="utf-8"?>
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:baselineAligned="false"
android:orientation="horizontal" >
<!-- static fragment for the left pane -->
<fragment
android:name="com.example.wbslideshow.ListFrag"
android:id="#+id/listFrag"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1" />
<FrameLayout
android:id="#+id/myImgContainer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="fill_parent">
</FrameLayout>
</LinearLayout>
img_frag.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="horizontal"
android:id="#+id/imgFrag">
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_ab_bottom_solid_dark_holo" />
</LinearLayout>
The code might not be perfect but this is not the issue here. In portrait-mode the app is working. Only in landscape mode i get a problem loading the listfrag.
Here is also the current logcat:
10-11 13:20:12.563: W/dalvikvm(5158): threadid=1: thread exiting with uncaught exception (group=0x414539a8)
10-11 13:20:12.583: E/AndroidRuntime(5158): FATAL EXCEPTION: main
10-11 13:20:12.583: E/AndroidRuntime(5158): java.lang.IllegalArgumentException: No view found for id 0x7f060041 (com.example.wbslideshow:id/myImgContainer) for fragment ImgFrag{417af140 #1 id=0x7f060041}
10-11 13:20:12.583: E/AndroidRuntime(5158): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:877)
10-11 13:20:12.583: E/AndroidRuntime(5158): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1057)
10-11 13:20:12.583: E/AndroidRuntime(5158): at android.app.BackStackRecord.run(BackStackRecord.java:694)
10-11 13:20:12.583: E/AndroidRuntime(5158): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435)
10-11 13:20:12.583: E/AndroidRuntime(5158): at android.app.FragmentManagerImpl$1.run(FragmentManager.java:441)
10-11 13:20:12.583: E/AndroidRuntime(5158): at android.os.Handler.handleCallback(Handler.java:725)
10-11 13:20:12.583: E/AndroidRuntime(5158): at android.os.Handler.dispatchMessage(Handler.java:92)
10-11 13:20:12.583: E/AndroidRuntime(5158): at android.os.Looper.loop(Looper.java:153)
10-11 13:20:12.583: E/AndroidRuntime(5158): at android.app.ActivityThread.main(ActivityThread.java:5299)
10-11 13:20:12.583: E/AndroidRuntime(5158): at java.lang.reflect.Method.invokeNative(Native Method)
10-11 13:20:12.583: E/AndroidRuntime(5158): at java.lang.reflect.Method.invoke(Method.java:511)
10-11 13:20:12.583: E/AndroidRuntime(5158): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
10-11 13:20:12.583: E/AndroidRuntime(5158): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
10-11 13:20:12.583: E/AndroidRuntime(5158): at dalvik.system.NativeStart.main(Native Method)
I can see there is a problem with "no vie found ..." but I do not know why. For me it seems to be that the layout file from res/layout-land is not loaded in landscape mode and therefore the onCreateView for the IMgFrag gets a problem.
But why?
Andreas
ID myImgContainer is available in layout layout-land/list_frag.xml, by the time the click event is called, only main_frag will be shown on the screen, so instead of R.id.myImgContainer in MainActivity user R.id.mycontainer itself.
You should not use fragment tag like that in the layout-land/list_frag.xml file.
list_frag.xml is the layout of your ListFrag class. You try to put ListFrag into it's own layout file. It's so wrong.
Do you want a ImageView below a list in portrait mode and a ImageView to the right of the list (like two panels) when in landscape mode?
If you want to do that. You just need to write your layout-land/list_frag.xml as below:
<?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="horizontal">
<LinearLayout
android:id="#+id/listFrag"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="#+id/startpath"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:height="40dp"
android:background="#C27302"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="#string/list_header"
android:textSize="16sp"
android:textStyle="bold" />
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill"
android:background="#B012EB" />
<TextView
android:id="#+id/empty"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:orientation="vertical">
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="#drawable/abc_ab_bottom_solid_dark_holo" />
</FrameLayout>
</LinearLayout>
You don't need the myImgContainer, so remove it from your layout/list_frag.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/listFrag"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/startpath"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:height="40dp"
android:background="#C27302"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="#string/list_header"
android:textSize="16sp"
android:textStyle="bold" />
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="312dp"
android:layout_gravity="fill"
android:background="#B012EB" />
<TextView
android:id="#+id/empty"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_ab_bottom_solid_dark_holo" />
</LinearLayout>
Change onstartFragBtnClicked method in MainActivity, only replace with the ListFrag. The platform will take care of which xml file to use as the ListFrag's layout.
public void onstartFragBtnClicked(String root)
{
ListFrag newListFrag = new ListFrag();
Bundle args = new Bundle();
args.putString(ListFrag.FRAG_MESSAGE_DEF_Input, root);
newListFrag.setArguments(args);
//change the fragments dynamically
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.mycontainer, newListFrag);
transaction.addToBackStack(null);
transaction.commit();
}

Categories

Resources