how change fragment textview with own java class? - java

I tried to change a TextView in Activity of Fragment in three cases, but I can't change the TextView.
Is there any solution to change a TextView of Fragment in own Fragment_Activity or Main_Activity?
Fragment.java
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
TextView textView = (TextView) getView().findViewById(R.id.textView1);
textView.setText("Done!");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_blank_fragment2, container, false);
TextView tv = (TextView) view.findViewById(R.id.textView1);
tv.setText("Done!");
return view;
}
#Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
TextView tv = (TextView) getView().findViewById(R.id.textView1);
tv.setText("Done!");
}
Fragment.xml
...
<TextView
android:textColor="#color/myBlack"
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
....
calling fragment class for view in MainActivity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_weixin);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
instance = this;
...
View view2 = mLi.inflate(R.layout.fragment_blank_fragment2, null);
views.add(view2);
...
}

Thing to know
In onCreate of fragment getView() returns null because still view in not created.
Create a method in fragment to set value for the TextView from activity using fragment instance.
Example :
Fragment
public class Fragment1 extends Fragment {
TextView tv;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_blank_fragment2, container, false);
tv = (TextView) view.findViewById(R.id.textView1);
tv.setText("Done!");
return view;
}
public void setViewText(String text){
tv.setText(text);
}
}
Activity
public class MyActivity extends FragmentActivity {
Fragment1 fragment1;
#Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
setContentView(R.layout.activity_fragment);
//as you are using static fragment so create fragment instance using findFragmentById(id)
fragment1 = (Fragment1) getSupportFragmentManager().findFragmentById(R.id.fragment1);
fragment1.setViewText("Message");
}
}
Visit Official doc Communicating with Other Fragments

Because we can't see the whole Fragment.xml file or the the xml of your main activity i can't tell for sure what's the problem but it seems like you may have not specified the fragment class in the Fragment.xml file so the oncreate never gets called. I would suggest you add the fragment attribute in your main_weixin xml and that you remove the view2 inflation in your main activity then you could simply add this in your main_weixin.xml:
<fragment
android:name="your_package_name.Fragment"
android:id="#+id/fragment_id"
android:layout_width="match_parent"
android:layout_height="match_parent" />

Related

Change the fragment to another fragment within a setOnclick

I have a simple block code and i wish pass this fragment to another fragment with a click in a button.
If anyone could help me I would appreciate it
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_inicio,container,false);
linearLayout = view.findViewById(R.id.clientea);
linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getActivity(),"Teste",Toast.LENGTH_SHORT).show();
}
});
return view;
}
I will show a simple way with code.
There are one Activity and two Fragments in the code.
First , the MainActivity contains the FragmentOne.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager().beginTransaction().add(R.id.container, new FragmentOne(), "")
.addToBackStack(null)
.commit();
}}
Then FragmentOne, there is a button in it, which will jump FragmentTwo when click.
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);
Button btnClick = view.findViewById(R.id.btn);
btnClick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.container, new FragmentTwo())
.addToBackStack(null)
.commit();
}
});
return view;
}}
The last is the FragmentTwo:
public class FragmentTwo extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_two, container, false);
return view;
}
}
I could give the xml if you want.
From my experience with Android development, the approach that is taken to this problem is to create a functional interface, implement the interface in the Activity that the fragments are managed by and then do the fragment swapping inside the method provided by the interface.
So first create an interface, let's call it IFragmentToSwap.
public interface IFragmentToSwap{
void OnButtonClicked();
}
Then in the Activity that controls fragment transactions you need to implement this interface.
public class MainActivity extends AppCompatActivity implements IFragmentToSwap {
#Override
public void OnButtonClicked()
{
//Swap fragment here
}
}
Now in your fragment in the OnAttach override method you should do the following:
private IFragmentToSwap mListener;
#Override
public void onAttach(Context context)
{
super.onAttach(context);
if (context instanceof IFragmentToSwap)
{
mListener = (MainActivity) context;
}
else
{
throw new RuntimeException(context.toString()
+ " must implement IFragmentToSwap");
}
}
And in the method you provided that is contained inside your fragment you would call the method on the functional interface when a click happens, like this:
#Override
public View onCreateView(final LayoutInflater inflater, final
ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_inicio,container,false);
linearLayout = view.findViewById(R.id.clientea);
linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mListener.OnButtonClicked();
Toast.makeText(getActivity(),"Teste",Toast.LENGTH_SHORT).show();
}
});
return view;
}
And don't forget to detach the listener in the OnDetach override:
public void onDetach()
{
super.onDetach();
mListener = null;
}
This is the most common approach I have seen to swapping fragments on Android.

communication between two fragments . I am not using any already defined view for any of the fragments. I am just adding fragments at runtime

I have two fragments MyFragment and MyFragment2 , an interface defined within MyFragment2.
code for MyFragment2:
public class MyFragment2 extends android.support.v4.app.Fragment implements View.OnClickListener {
public interface MyInterface2
{
public void respond(String s);
}
EditText editText;
Button sendData;
MyInterface2 comm;
View v=getView();
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
v = inflater.inflate(R.layout.my_fragment_2,container,false);
return v;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
this.comm = (MyInterface2)getActivity();
editText = (EditText)getActivity().findViewById(R.id.text);
sendData =(Button)getActivity().findViewById(R.id.sendData);
sendData.setOnClickListener(this);
}
#Override
public void onClick(View v) {
try {
String s = editText.getText().toString();
comm.respond(s);
}
catch(Exception e)
{
Toast.makeText(getActivity(),"error:"+e,Toast.LENGTH_LONG).show();
}
}
}
I am trying to send the content of editText from MyFragment2 to the fragment MyFragment by pressing the button (Myfragment2 initially set on the main activity's view using the Java code)
The main activity's code is as follows*(my_layout is the id of layout in which I am putting the fragments)*:
public class MainActivity extends AppCompatActivity implements MyFragment2.MyInterface2 {
//String data;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyFragment2 fragment2= new MyFragment2();
FragmentManager fManager= getSupportFragmentManager();
FragmentTransaction transaction= fManager.beginTransaction();
transaction.add(R.id.my_layout,fragment2,"MyFragment2");
transaction.commit();
}
public void respond(String s)
{
MyFragment fragment = new MyFragment();
FragmentManager fManager =getSupportFragmentManager();
FragmentTransaction transaction = fManager.beginTransaction();
transaction.replace(R.id.my_layout,fragment);
transaction.commit();
fragment.getData(s);
}
}
when I click the sendData button in fragment MyFragment2 , MyFragment2 gets replaced with fragment Myfragment but no data change occurs in the MyFragmnet's textView and an error is also shown which I have catched in a try catch block from fragment MyFragment2(here is the image for that).
code for MyFragment :
public class MyFragment extends android.support.v4.app.Fragment {
TextView textView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v= inflater.inflate(R.layout.my_fragment,container,false);
//textView =(TextView)v.findViewById(R.id.getText);
return v;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
textView =(TextView)getActivity().findViewById(R.id.getText);
}
public void getData(String data)
{
textView.setText(data);
}
}
You can easily pass data between fragments using a callback or passing the arguments via a bundle.
Check out this article:
https://developer.android.com/training/basics/fragments/communicating.html
onActivityCreated is no need. Uncomment ur text view initiation statement in onCreateView block.
Ensure you have text view in your respective layout file with same id you have passed

java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference

I have a BlankFragment
package com.hfad.addingafragmenttoframelayout;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.w3c.dom.Text;
/**
* A simple {#link Fragment} subclass.
*/
public class BlankFragment extends Fragment {
public BlankFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("message","onCreateView() of BlankFragment");
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank, container, false);
}
public void setText(String textToBeSet){
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
tv.setText(textToBeSet);
}
}
and it's layout is:
<FrameLayout 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="com.hfad.addingafragmenttoframelayout.BlankFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/hello_blank_fragment"
android:id="#+id/fragmentText"/>
</FrameLayout>
Here is the MainActivity
package com.hfad.addingafragmenttoframelayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//BlankFragment bf = new BlankFragment();
//getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, bf).commit();
BlankFragment bf = new BlankFragment();
bf.setText("hello world");
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, bf).commit();
}
}
and here is the layout of MainActivity
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="com.hfad.addingafragmenttoframelayout.MainActivity"
android:orientation="vertical">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/fragment_container"
/>
</LinearLayout>
In the onCreate method of activity I am adding fragment to layout. This works fine unless I try to change the Text using setText method.
And I get this error:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
at com.hfad.addingafragmenttoframelayout.BlankFragment.setText(BlankFragment.java:35)
at com.hfad.addingafragmenttoframelayout.MainActivity.onStart(MainActivity.java:29)
referring to this line
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
Can somebody explain what's causing this exception?
Don't
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("message","onCreateView() of BlankFragment");
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank, container, false);
}
public void setText(String textToBeSet){
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
tv.setText(textToBeSet);
}
Do
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View RootView = inflater.inflate(R.layout.fragment_blank, container, false);
TextView tv = (TextView)RootView.findViewById(R.id.fragmentText);
tv.setText("HI");
return RootView;
}
Here:
bf.setText("hello world");
line causing issue, becuase calling setText method of Fragment before adding Fragment in FragmentManager.
Call setText method after adding bf Fragment:
getSupportFragmentManager().beginTransaction().
add(R.id.fragment_container, bf).commit();
bf.setText("hello world"); // call here
The problem is FragmentTransaction is async by default
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, BlankFragment.newInstance);
ft.disallowBackStack();
ft.commitNowAllowingStateLoss();
Then you still can't get the Fragment yet, you have to get it from the FragmentTransaction
BlankFragment bf = (BlankFragment) getSupportFragmentManager().getFragmentById(R.id.fragment_container);
bf.setText("hello world");
This article helped me to understand this problem better
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
do it in onCreateView();
You can use a temporary variable that can hold the String while the View is not yet created.
private TextView tv;
private String holder = "";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_blank, container,false);
tv = (TextView)v.findViewById(R.id.fragmentText);
return v;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
tv.setText(holder);
}
public void setText(String textToBeSet){
if(tv != null){
tv.setText(textToBeSet);
}else{
holder = textToBeSet;
}
}
My assumption is that you want to instantiate your BlankFragment with some initial text as well as allowing the text to be set later on from your MainActivity.
In that case I would first change the the Fragment to accept an initial text like so:
public class BlankFragment extends Fragment {
private static final String ARG_INITIAL_TEXT = "arg_initial_text";
public static BlankFragment newInstance(CharSequence initialText) {
final BlankFragment fragment = new BlankFragment();
final Bundle args = new Bundle();
args.putCharSequence(ARG_INITIAL_TEXT, initialText);
fragment.setArguments(args);
return fragment;
}
public BlankFragment() {
// Required empty public constructor
}
private CharSequence mInitialText;
private TextView mText;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mInitialText = getArguments().getCharSequence(ARG_INITIAL_TEXT);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("message", "onCreateView() of BlankFragment");
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mText = view.findViewById(R.id.fragmentText);
mText.setText(mInitialText);
}
public void setText(CharSequence textToBeSet) {
mText.setText(textToBeSet);
}
}
The Activity code would then look like the following:
public class MainActivity extends AppCompatActivity {
private BlankFragment mBlankFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
final Fragment bf = BlankFragment.newInstance("hello world");
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, bf, BlankFragment.class.getName())
.commit();
}
mBlankFragment = (BlankFragment) getSupportFragmentManager()
.findFragmentByTag(BlankFragment.class.getName());
}
private void someTimeLaterWhenWantingToSetNewTextToFragmentFromActivity(CharSequence newText) {
if (mBlankFragment != null) {
mBlankFragment.setText(newText);
}
}
}
Note that the null-check of savedInstanceState is to guard for Activity-recreation for instance due to configuration changes.

How can I find the null pointer error in this Android Code involving Fragments

I have been trying for 2 hours now to find the null pointer in my code and am having no luck. I am hoping one of you far smarter individuals than I can figure it out. First off, I am following the tutorial here: http://youtu.be/Y2liEQV3tbQ?list=PLonJJ3BVjZW4lMlpHgL7UNQSGMERcDzHo by slideNerd.
Here is what is baffling me: When in horizontal mode, the code executes perfectly and the displays are updated with correct information. This means that the horizontal portion of the if statement is working. When it is in portrait however and I click a list view icon, it immediately force closes with null pointer. The error comes from the line that reads:
f2b.changeTextView(index);
If I remove that line, the second activity opens without a problem. I am simply at a loss as to what has been causing me so much trouble.
Here are my classes:
MainActivity:
public class MainActivity extends Activity implements FragmentA.Communicator{
private FragmentA f1a;
private FragmentB f2b;
private FragmentManager manager;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
manager=getFragmentManager();
f1a = (FragmentA) manager.findFragmentById(R.id.fragment1a);
f1a.setCommunicator(this); //the respond method that is implemented from Fragment a
f2b = (FragmentB) manager.findFragmentById(R.id.fragment2b);
}
#Override
public void respond(int index) {
//Check if portrait mode
if (f2b != null && f2b.isVisible()){ //Horizontal
f2b.changeTextView(index);
} else { //Vertical
Intent intent = new Intent(this, Activity2.class);
intent.putExtra("index", index);
startActivity(intent);
}
}
}
Fragment A:
public class FragmentA extends Fragment implements AdapterView.OnItemClickListener {
ListView listView;
Communicator comm;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_a, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
listView = (ListView) getActivity().findViewById(R.id.fragment_a_list_view);
ArrayAdapter adapter = ArrayAdapter.createFromResource(getActivity(), R.array.chapters, android.R.layout.simple_list_item_1);
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
comm.respond(position);
}
public void setCommunicator(Communicator communicator){
this.comm = communicator;
}
//Interface to allow access between fragments
public interface Communicator{
public void respond(int index);
}
}
Fragment B:
public class FragmentB extends Fragment {
TextView textView;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_b, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
textView = (TextView) getActivity().findViewById(R.id.fragment_b_text_view);
}
public void changeTextView(int position){
String [] descriptions = getResources().getStringArray(R.array.descriptions);
textView.setText(descriptions[position]);
}
}
Activity2:
public class Activity2 extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity2);
Intent intent = getIntent();
int index = intent.getIntExtra("index", 0);
//reference the fragment
FragmentB f2b = (FragmentB) getFragmentManager().findFragmentById(R.id.fragment2b);
if (f2b != null){
f2b.changeTextView(index);
}
}
}
And Here is the error code in the logcat:
Caused by: java.lang.NullPointerException
at com.pgmacdesign.fragmentexamples3_flexibleui.FragmentB.changeTextView(FragmentB.java:42)
at com.pgmacdesign.fragmentexamples3_flexibleui.Activity2.onCreate(Activity2.java:25)
I have already confirmed that the index/ position variable is passing correctly. If anyone has any suggestions as to how to find the null pointer error, I would love the assistance.
In your Fragment B,
Try to replace textView = (TextView) getActivity().findViewById(R.id.fragment_b_text_view) by textView = (TextView) view.findViewById(R.id.fragment_b_text_view) and move it from onActivityCreated() to onCreateView().
Hope this helps.
I think your problem is when you can try to find the ID.
Try this textView = (TextView) view.findViewById(R.id.fragment_b_texT_view) where this view is your View view = inflater.inflate(R.layout.fragment_b, container, false);.

How to add new Controls (Buttons, TextViews) to a Fragment dynamically

Here's my fragment class:
public class FirstFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
EditText newText = new EditText(getActivity());
newText.setText("This is a fragment");
newText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
return inflater.inflate(R.layout.fragment_first, container, false);
}
}
I am trying to add newText to the fragment being created.
simply store the view that was returned from the inflater.inflate call , and add anything you want to it .
in the end , return the stored view .

Categories