I'm using a button to call a method that just places input text into a textview. Whenever I use findViewById, it returns null.
public void encode(View view){
TextView out = (TextView) view.findViewById(R.id.encoderout);
EditText in = (EditText) view.findViewById(R.id.encoderin);
out.setText(in.getText().toString());
out.setTypeface(font);
}
My xml is here
<?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"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
>
<EditText android:id="#+id/encoderin"
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="wrap_content"
android:hint="Text to encode"/>
<Button android:id="#+id/encoderbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="encode"
android:text="Encode!"/>
</LinearLayout>
<TextView android:id="#+id/encoderout"
android:text="test"
android:layout_width="fill_parent"
android:layout_weight="1"
android:gravity="center"
android:layout_height="wrap_content"/>
</LinearLayout>
Almost every post I could find said that cleaning the project helped solve the problem but not in this case.
EDIT: ADDITIONAL INFO
I'm using Fragments, and this is my fragment code
public static class Encoder extends Fragment{
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.encoder, container, false);
return view;
}
}
It's calling up into the Activity because of the way buttons work. I can call the find methods fine in the fragment, but not when I have to go back to the activity.
I can verify the view is not null, it prints out fine when the toString is called in the method.
Solution: Never realized that I had to use the main view, thought I was SUPPOSE to use the button view. I'm very new to this (started today) thankyou everyone for the input!
<Button android:id="#+id/encoderbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="encode"
android:text="Encode!"/>
The parameter view in callback method encode(View view) in the Java code is supplied with the Button view itself but not the Activity.
See Reference below:
http://developer.android.com/reference/android/widget/Button.html
Fragments don't receive onClicks methods that are declared in the XML. You need to define encode in your Activity instead, then direct the desired behavior to the appropriate Fragment. Annoying, but that's the way it's done. I suggest you just implement the OnClickListener programatically in your Fragment code to avoid intertwining the behavior of your fragment and activity.
Related
This question already has answers here:
findViewById in Fragment
(37 answers)
Closed 2 years ago.
How to access an attribute in the activity xml?
I want to use it in fragment.
for example : this is my activity xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
xmlns:fab="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
fab:layout_constraintTop_toTopOf="parent"
fab:layout_constraintLeft_toLeftOf="parent"
fab:layout_constraintRight_toRightOf="parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/layTitle"
android:layoutDirection="rtl"
android:background="#color/colorPrimary"
android:padding="#dimen/paddingTitle"
android:elevation="#dimen/elevationActivityTitle"
android:layout_alignParentTop="true">
<ImageView
fab:layout_constraintLeft_toLeftOf="parent"
fab:layout_constraintTop_toTopOf="parent"
fab:layout_constraintBottom_toBottomOf="parent"
android:layout_width="#dimen/imgActivityTitle"
android:layout_height="#dimen/imgActivityTitle"
android:id="#+id/btn_back"
android:src="#drawable/ic_back"
android:elevation="5dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<FrameLayout
android:id="#+id/frag"
android:layout_width="0dp"
android:layout_height="0dp"
fab:layout_constraintBottom_toBottomOf="parent"
fab:layout_constraintTop_toBottomOf="#+id/layTitle"
fab:layout_constraintLeft_toLeftOf="parent"
fab:layout_constraintRight_toRightOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
I want findViewByid ImageView in fragment
When I was searching for solution I got the following one:
TextView btn_back= (TextView) getView().findViewById(R.id.btn_back)
But, unfortunately it was not working for me.
You can use the interface to do it :
Create an interface names IBtnClick with one void method: "void onBtnClicked();"
use interface in activity like this:
IBtnClick iBtnClick= (IBtnClick)getActivity();
here getAtivity is our context, if it doesn't work use another scope context.
and use your method in button click listener like this
iBtnClick.onBtnClicked();
Now in your fragment you have to implements interface and
you can add any action you want in Overrided method.
Use either viewModel or interfaces to talk between activity and fragment. don't try to send the button to fragment but trigger it from there. That will prevent any leaks or null pointers.
Ok. You have some options.
Firstly, you can access these variables to directly in fragment like that.
MainActivity.java
TextView backButton;
backButton = findViewById(R.id.btn_back);
Fragment.java
((MainActivity) getActivity()).backButton
You can get current activity with getActivity() but Java compiler cannot understand which activity so have to cast to MainActivity.
Secondly, you can pass your activity instance to fragment. You can use constructors and newInstance() function. You can read that post Best practice for instantiating a new Android Fragment
In my opinion, I prefer second option because you guarantee these variables that include activity class. Some devices occur errors at first option. But second option uses more ram because you are passing your variables to another class.
The choice is yours
Try This code
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.recharge_plane_fragment, container, false);
alertdialog_Listview=view.findViewById(R.id.alertdialog_Listview);
return view;
}
You can declare your TextView btn_back as static in activity
public static TextView btn_back;
btn_back = (TextView) findViewById(R.id.btn_back);
and get it in fragment
TextView btn_back = ((MainActivity)getActivity()).btn_back;
In my application, I want the user to be able to do 3 things:
Open a dialog.
Allow the user to input two strings within that dialog.
Click an "Okay" button, and have the two strings passed back to the calling activity.
I am trying to follow the example Here, but it's not going well.
This is what I have:
<?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="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="Some Text Here"
android:textSize="18sp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
style="#style/my_custom_style"
android:text="From: "
android:labelFor="#+id/from"/>
<EditText
android:id="#+id/from"
style="#style/my_custom_style"
android:inputType="date"/>
<TextView
style="#style/my_custom_style"
android:text="To: "
android:labelFor="#+id/to"/>
<EditText
android:id="#+id/to"
style="#style/my_custom_style"
android:inputType="date"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_gravity="end"
android:orientation="horizontal">
<Button
android:id="#+id/button_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/cancel"/>
<Button
android:id="#+id/button_okay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/okay"/>
</LinearLayout>
</LinearLayout>
And here is my class that extends DialogFragment:
public class MyCustomDialogFragment extends DialogFragment
{
#Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
LayoutInflater layoutInflater = getActivity().getLayoutInflater();
alertDialogBuilder.setView(layoutInflater.inflate(R.layout.my_custom_layout, null));
return alertDialogBuilder.create();
}
}
Now, in my calling activity I am trying to do this:
MyCustomDialogFragment myCustomDialogFragment = new MyCustomDialogFragment();
// Since the onCreate() method of my custom DialogFragment returns an android.app.Dialog, I thought I could do this:
Dialog dialog = new CustomDialogFragment();
Of course, this did work, I get the:
Incompatible types.
Required: android.app.Dialog
Found: com.me.MyCustomDialogFragment
error, even though the onCreate() method does return android.app.Dialog. I cannot even cast it to Dialog. So, how can I accomplish my 3 goals from above?
There are "a lot" of examples out there, but they are all just variations on the default Google example, which is not very thorough.
how can I accomplish my 3 goals from above?
Open a dialog.
Call show() on your MyCustomDialogFragment instance, passing in a FragmentManager. While the framework DialogFragment is deprecated, its JavaDocs show how to use show().
Allow the user to input two strings within that dialog.
Your layout seems to offer this, though you will want to get rid of your buttons, since AlertDialog provides those.
Click an "Okay" button, and have the two strings passed back to the calling activity.
Call setPositiveButton() on your AlertDialog.Builder. Have the DialogInterface.OnClickListener that you pass into setPositiveButton() get the values out of your EditText widgets and get that data to your activity (e.g., use a shared ViewModel between this fragment and the activity, and have the fragment update LiveData in the ViewModel with the EditText contents).
This sample app shows the basics of using DialogFragment, albeit using the since-deprecated framework DialogFragment implementation and not using ViewModel.
I am trying to understand the following fragment code:
public class FragmentA extends Fragment {
public FragmentA(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if(container!=null)
// WHY IS THIS CODE EXECUTED? I did not set container variable
// why if I pass null insted of Container, I get the same result?
return inflater.inflate(R.layout.fragment_a,container,false);
}
}
This ViewGroup container I never initialized or something. How does android know what is my container?, if I never initialized it.
The other thing that is not clear to me is when I call inflate and if instead the container I write null, the result is same.
return inflater.inflate(R.layout.fragment_a,null,false);
I am working with ViewPager in my main activity.
I create the fragment is this way in the FragmentPagerAdapter:
Fragment fragment = new FragmentA();
These are my xml files:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"/>
and for the fragment :
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFCC00" >
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:gravity="center"
android:textColor="#ffffff"
android:textStyle="bold"
android:text="THIS IS FRAGMENT A" />
</FrameLayout>
EDIT:
I found this on the developer site:
The container parameter passed to onCreateView() is the parent
ViewGroup (from the activity's layout) in which your fragment layout
will be inserted. The savedInstanceState parameter is a Bundle that
provides data about the previous instance of the fragment, if the
fragment is being resumed (restoring state is discussed more in the
section about Handling the Fragment Lifecycle).
But, is still not clear for me. I did not pass any ViewGroup to the Fragment in the Fragment call....
The container is supplied externally to the fragment. It's either generated automatically when you use the <fragment> tag in xml, or it's passed as part of the FragmentTransaction when you initialize the fragment in code.
I am building a view with 2 fragments inside it. Inflating the layout works fine. But I got another problem. Before creating these fragments I need to pass some data to those fragments (FragmentListSchema and FragmentSchemaDetail).I thought of application variables but I guess that's not the proper way. How can I do it ?
Thanks in advance
Inflate :
public class FragmentSchemaTotal extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.fragment_schema,container);
return view;
}
}
Layout :
<?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">
<fragment android:name="kine.gui.FragmentListSchema"
android:id="#+id/list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment android:name="kine.gui.FragmentSchemaDetail"
android:id="#+id/viewer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
Use Fragment setArguments to pass data
FragmentSchemaTotal fragment = new FragmentSchemaTotal();
Bundle bundle = new Bundle();
bundle.putString("data","your data");
fragment.setArguments(bundle);
Why not use loaders inside of the fragments to have them load the data themselves? The usefulness of the Loader kind of depends on what type of data you are dealing with, though. It's tough to suggest the proper way without knowing more.
If Loaders don't fit the bill, you could have the activity find the fragment and set the data on them. Until that happens, the fragment could display a spinner instead of it's view. Once the data is set, the fragment can then display it's views.
The last alternative is to create the fragments in code and pass arguments to them. This isn't quite as flexible though. I would recommend the loader.
Hello I'm writing a little Android app (Version 2.3.3). Now i get this strange NullPointer Exception in this very basic code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainmenu);
newDeck = (Button) findViewById(R.id.newDeckB);
loadDeck = (Button) findViewById(R.id.loadDeckB);
viewEdition = (Button) findViewById(R.id.viewEditionB);
newDeck.setOnClickListener(this);
loadDeck.setOnClickListener(this);
viewEdition.setOnClickListener(this);
}
Im using this simple layout at the moment in main menu.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">
<Button android:id="#+id/newDeckB"
android:text="New Deck"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<Button android:id="#+id/loadDeckB"
android:text="Load Deck"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<Button android:id="#+id/viewEditionB"
android:text="View Edition"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<TextView android:id="#+id/currentDeckTextView"
android:text="Default Deck"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Now my problem is a nullpointexception in line 25, which is the line where i set the first clickListener
newDeck.setOnClickListener(this);
Using the debugger i figured out that the button newDeck is null. I searched a lot in the web but the only answer to such kind of problem was to check that the setContentView is set before the findViewById. This is obviously the case here.
I would be very glad for any kind of advice.
Thx in Before!
Get your views and set the listeners in onPostCreate() method.
There are two events that the App expects, onCreate(), and onStart()
Which one you put this function in, matters.
I had to move "findViewByID" from onCreate() to onStart()
#Override
protected void onStart() {
// use findViewById() here instead of in onCreate()
}