Null Pointer Exception Android - java

I am trying to make a button, count clicks and display them in a text view.
Tried everything i knew.
XML:
<LinearLayout
android:id="#+id/gpulay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="20dp" >
<TextView
android:id="#+id/master_control_text_gpulay"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Master Control :"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="#+id/plus_gpulay"
android:layout_width="35dp"
android:layout_height="35dip"/>
</LinearLayout>
Here is my code:
public class Main extends Fragment {
int c=0;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (container == null) {
return null;
}
ListView GPU_LAYOUT = (ListView)inflater.inflate(R.layout.gpu, container, false);
TextView text = (TextView) GPU_LAYOUT.findViewById(R.id.text1);
Button plus = (Button) GPU_LAYOUT.findViewById(R.id.butt1);
plus.setOnClickListener(new OnClickListener() { //null pointer this line, but it's from .srtText i think
public void onClick(View v) {
c++;
text.setText(c);
}
});
}
return GPU_LAYOUT;
}
App force closes when i open it, so i don't even see the main layout.

The NPE is coming from here
text.setText(c);
you are using the wrong setText() method. When you place an int in there it looks for a resource with that id. You need to give it a String. You can do this several ways. One way is to change it to
text.setText("" + c);
You could also do
text.setText(String.valueOf(c));
TextView Docs notice the different methods.

Its just wrong to create your app in onCreateView while working in an Activity.
You can still do all this in your onCreate Method.
My Guess would be that GPU_Layout is null or doesnt contain your button. Thats why button (plus) is Null and calling setOnClickListener on it throws a NullPointerException.
Also it would help if you could explain WHEN the error Occurs, during inflating/building the Activity or during actually pressing the Button

1) You need to extend your class from Fragment instead of Activity. Then your method onCreateView will work. Then set this fragment as contentView of your Activity.
2) You can't set int as text of textView or any other widget. You need to convert it into String first using String.valueOf(count);

Related

Using ViewPager2 to step-by-step SignUp form with Fragments

I'm trying to implement a SignUp form with viewpager2 where the user is asked to input its name, password, phone number and photo in a 4-step sequential prompt. So I have an activity that contains a ViewPager2, 4 different fragments and 4 different classes - one for each prompt.
Each layout has an EditText for the input and a "Next" Button for the submit and going to the next item on viewpager. For each fragment the input is validated at typing and its "Next" button becomes green and clickable when validated (ex: phone has more than 6 characters). This can be seen in the example-code I show below. (Please understand that I removed some code in order to be more clear)
example-layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/et_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:lines="1" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="#+id/bt_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="next" />
</LinearLayout>
</LinearLayout>
example-fragment-class.java: (example of password, but name, phone, are very similar)
public class PasswordFragment extends Fragment implements APIConnectionCallback {
private FragmentPasswordBinding passwordBinding;
private final AuthActivity parent;
private boolean isValidInput = false;
public PasswordFragment(AuthenticationActivity parent) {
this.parent = parent;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater,
#Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
return FragmentPasswordBinding.inflate(inflater, container, false).getRoot();
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// saves password in shared preferences (to capture it at the last viewpager item and submit) and changes viewpager to the next item
passwordBinding.btNext.setOnClickListener(view -> {
SharedPreferences sharedPreferences = parent.getSharedPreferences(AuthenticationActivity.AUTHENTICATION_CREDENTIALS, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("password", Objects.requireNonNull(passwordBinding.etPassword.getText()).toString());
editor.apply();
parent.getViewPager().setCurrentItem(parent.getViewPager().getCurrentItem() + 1, true);});
}
#Override
public void onStart() {
super.onStart();
passwordBinding.btNext.setOnClickListener(view -> {
if(isValidInput) {
// queries the server if submit is clicked and input is valid
}
});
// validates input while typing
passwordBinding.etPassword.addTextChangedListener(
new Validator.TextValidator(passwordBinding.etLoginPassword) {
#Override
public void validate(TextView textView, String password) {
isValidInput = Validator.matches(password, Validator.VALIDATION_KEY.PASSWORD);
submitButtonStateChange(); // changes the "clickability" of the submit button
}
}
);
}
private void submitButtonStateChange() { // this is repeating code for all fragments
passwordBinding.btNext.setBackgroundTintList(getActivity().getBaseContext().getColorStateList(
isValidInput ? R.color.green : R.color.black
));
}
}
My code is working but feels like a mess and too repetitive. For each Fragment class the button behaviour is very similar (only changes the type of validation). There must be a 'smarter way' of doing this without all the repeating code and all the different 4 classes + 4 layouts. Thought of using an abstract Fragment that generalizes some of the repeating code for the Fragment classes, but still it doesn't solve the necessity of having all those classes and layouts.
I could imagine doing this with a single Fragment class that changes implementation of its methods according to its position within the viewpager, but can't materialise this into a working code.
Is there any good idea or practice in order to tackle something like this?

Update view elements after transition change on android

I've got a transition on the app I'm developing that fades all elements of a frame layout and swaps them for other elements. The animation works as intended, but from there I can't interact with the buttons on the new scene applied to the fragment. Here is the relevant parts of the code:
This is the frame layout where the animation happens
<FrameLayout
android:id="#+id/scene_root_index"
android:layout_width="match_parent"
android:layout_height="360dp"
app:layout_constraintBottom_toTopOf="#+id/indexSearchButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/imageView4">
<include layout="#layout/main_scene" />
</FrameLayout>
This is the main_scene:
<!--[...]-->
<ImageButton
android:id="#+id/newsMainIndexBtn"
android:layout_width="100dp"
android:layout_height="100dp"
android:backgroundTint="#00FFFFFF"
android:contentDescription="#string/descripcion_boton_noticias"
app:layout_constraintTop_toBottomOf="#+id/imageView6"
app:srcCompat="#drawable/ic_noticias"
tools:layout_editor_absoluteX="59dp" />
<!--[...]-->
This is the news scene, here is where I need the back button to work:
<!--[...]-->
<ImageButton
android:id="#+id/newsBack"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:backgroundTint="#00FFFFFF"
app:srcCompat="#drawable/ic_back" />
<!--[...]-->
This is the onCreateView method I'm using
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
setMainActivity((MainActivity) getActivity());
View view = inflateFragment(R.layout.fragment_index, inflater, container);
assert view != null;
sceneRoot = (ViewGroup) view.findViewById(R.id.scene_root_index);
mainScene = Scene.getSceneForLayout(sceneRoot, R.layout.main_scene, getActivity());
newsScene = Scene.getSceneForLayout(sceneRoot, R.layout.news_scene, getActivity());
transitionManagerForIndexScene = TransitionInflater.from(getActivity()).inflateTransitionManager(R.transition.transition_manager_for_index_scene, sceneRoot);
AppCompatImageButton news = view.findViewById(R.id.newsMainIndexBtn);
news.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
TransitionManager.go(newsScene);
}
});
The only solution that I've been able concieve is to make another layout with the same elements as the main one swapping out the frameView, but that animates all the screen and I feel like this is the correct way to do it, but I'm missing something.
I've tried to create the onclick event for the button everywhere in the code, but I couldn't find a place or time when the code recognized it, instead giving me a null pointer exception everytime.
Thanks for your time and for the help, I'm looking forward to be able to solve this issue.

Duplicating Form Layout on Click

I have a form that gives the user the option to add more fields to fill. The user adds more fields by clicking on a button. When the button is clicked It duplicates a RelativeLayout that houses form elements in it inside of another RelativeLayout.
This is the form that I'm trying to duplicate
<RelativeLayout
android1:id="#+id/questionTemplate"
android1:layout_width="wrap_content"
android1:layout_height="60dp"
android1:layout_alignParentLeft="true"
android1:layout_below="#+id/TextView01"
>
<Button
android1:id="#+id/Button02"
android1:layout_width="75dp"
android1:layout_height="20dp"
android1:layout_alignParentBottom="true"
android1:layout_alignParentRight="true"
android1:background="#drawable/purplebutton"
android1:text="BROWSE"
android1:textColor="#drawable/button_text_color"
android1:textSize="10sp"
/>
<EditText
android1:id="#+id/EditText02"
android1:layout_width="match_parent"
android1:layout_height="25dp"
android1:layout_above="#+id/Button02"
android1:layout_alignParentLeft="true"
android1:background="#drawable/textlines"
android1:ems="10"
android1:hint="50 WORDS OR LESS"
android1:inputType="textMultiLine"
android1:paddingLeft="5dp"
>
<requestFocus />
</EditText>
<TextView
android1:id="#+id/TextView03"
android1:layout_width="wrap_content"
android1:layout_height="wrap_content"
android1:layout_alignParentBottom="true"
android1:layout_marginRight="19dp"
android1:layout_toLeftOf="#+id/Button02"
android1:text="ADD PICTURE OR VIDEO"
android1:textSize="10sp"
/>
</RelativeLayout>
Its inside another RelativeLayout with an id of "questionsContainer". And when the user clicks on a button with an id of "makeLayoutButton" its supposed to add another instance of "questionTemplate" below another one.
Here's what I'm doing when the user clicks on the button
public void onClick(View v) {
Toast toast;
switch (v.getId()) {
case R.id.makeLayoutButton:
LayoutInflater vi = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v1 = vi.inflate(R.layout.make_question, null);
// template to be copied
RelativeLayout target = (RelativeLayout) v1.findViewById(R.id.questionTemplate);
// insert into main view
RelativeLayout insertPoint = (RelativeLayout)findViewById(R.id.questionsContainer);
insertPoint.addView(target);
break;
}
}
But it keeps crashing and the log informs me that I need to call removeView on the parent first. But when I do that it just removes all the children of the container and leaves me with one copy of the form without it duplicating. Any clues as to where I'm going wrong? I have a feeling it has something to do ids.
Of course, the output is correct. You're trying to add a View which already exists. You don't create (duplicate) new View but use the existing one by using findViewById() method.
In order to create the actual View, you should use inflate() method:
RelativeLayout target = (RelativeLayout) v1.inflate(R.id.questionTemplate, null); // if v1 is container for this R.id.questionTemplate layout

Null pointer Exception at Onclicklistener in android

How to recover the problem of Null pointer exception in the place of menu.setOnClickListener(new View.OnClickListener() {
,
i have an imageview(menu) if i press on that another activity(about page) should get opened, but here on OnClick of imageview, i'm getting above error and app gets force close.
Here's the code
public class About extends Activity {
LinearLayout line1, line2;
ImageView menu;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
menu = (ImageView)findViewById(R.id.menu);
menu.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
menu.setVisibility(View.VISIBLE);
// TODO Auto-generated method stub
line1.setVisibility(View.VISIBLE);
if (line2.getVisibility() == View.INVISIBLE || line2.getVisibility() == View.GONE) {
line2.setVisibility(View.VISIBLE); }
else {
line2.setVisibility(View.INVISIBLE);
}
}
});
ImageView about = (ImageView) findViewById(R.id.about);
about.setOnClickListener(new View.OnClickListener() {
public void onClick(View v){
startActivity(new Intent(About.this, About.class));
}
});
xml file
<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:background="#color/black" >
<LinearLayout
android:id="#+id/ll1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/black"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true">
<ImageView
android:id="#+id/menu"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/menu" />
</LinearLayout>
<LinearLayout
android:id="#+id/ll2"
android:layout_width="199dp"
android:layout_height="wrap_content"
android:background="#color/black"
android:layout_toRightOf="#+id/ll1"
android:visibility="gone"
>
<ImageView
android:id="#+id/about"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_above="#+id/textView1"
android:layout_toLeftOf="#+id/jobs"
android:src="#drawable/about" />
</LinearLayout>
<TextView
android:id="#+id/textView3"
android:layout_width="match_parent"
android:layout_height="50dip"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:background="#color/white"
android:textColor="#color/white"/>
you are getting NullPointerException because you didn't have initialize imageview.please do it first.
ImageView menu=(ImageView)findViewById(R.id.menu);
write this line before you set onClick Listener to your image view and you are done.hope it will help.
As I suspected, you have declared menu as an instance variable (at the top of your class), but you never instantiate it as a local variable. Add the line
menu = (ImageView)findViewById(R.id.menu)
at the top of your onCreate() method, BEFORE you set the OnClickListener, and it will work.
There is a difference between declaring the instance variable (which you have done) and actually initializing it. In this sense, you can look at the onCreate() method like a constructor in a regular java class. It's not enough to declare the variable at the top of the class, you have to initialize it as a variable of the actual object.
This might sound trivial, but believe me it's not. When I was first learning java, before I wrapped my head around this concept, I spent many hours screaming at the screen over the same sorts of errors you're having now.
You've not properly initialized the menu variable before setting listener you should
menu = (ImageView)findViewById(id.menu);
then write your listen line....
You should pass the context of the activity which is running not the activity that you desire to run,the Problem is About.this , Replace it with the context of current Activity
startActivity(new Intent(About.this, About.class));
you have not Instantiate menu 1st instantiate.
You are calling the same class with in the same activity change your following code as following
startActivity(new Intent(About.this, About.class));
to
startActivity(new Intent(getApplicationContext(), NewClass.class));
or
startActivity(new Intent(CurrentClass.this, NewClass.class));
I had a similar issue. I found the xml id I'd used in findViewById() came from a different page layout than the one active at the time.
No warnings. Just need to make sure common buttons like Save have a good naming convention.

Androids ExpandableListView - where to put the button listener for buttons that are children

I have been playing around a lot with the ExpandableListView and I cannot figure out where to add the button listeners for the button that will be the children in the view. I did manage to get a button listener working that uses getChildView() below, but it seems to be the same listener for all the buttons.
The best case scenario is that I would be able to implement the button listeners in the class that instantiates the ExpandableListAdapter class, and not have to put the listeners in the actual ExpandableListAdapter class. At this point I don't even know if that is possible
I have been experimenting with this tutorial/code: HERE
getChildView()
#Override
public View getChildView(int set_new, int child_position, boolean view, View view1, ViewGroup view_group1)
{
ChildHolder childHolder;
if (view1 == null)
{
view1 = LayoutInflater.from(info_context).inflate(R.layout.list_group_item_lv, null);
childHolder = new ChildHolder();
childHolder.section_btn = (Button)view1.findViewById(R.id.item_title);
view1.setTag(childHolder);
childHolder.section_btn.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
Toast.makeText(info_context, "button pushed", Toast.LENGTH_SHORT).show();
}
});
}else {
childHolder = (ChildHolder) view1.getTag();
}
childHolder.section_btn.setText(children_collection.get(set_new).GroupItemCollection.get(child_position).section);
Typeface tf = Typeface.createFromAsset(info_context.getAssets(), "fonts/AGENCYR.TTF");
childHolder.section_btn.setTypeface(tf);
return view1;
}
Any help would be much appreciated. Thank you and I will be standing by.
If the buttons are in the ExpandableListView, their listener needs to be in the adapter.
I'm not sure the thrust of your question, but if you are asking how do you relate the button to the contents of the child row, I can answer that. :p
I'll assume a somewhat simple child row layout for demonstration purposes.
child_row.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="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<TextView
android:id="#+id/ListItem1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left|center_vertical"
android:paddingLeft="7dip"
android:paddingRight="7dip"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/ListItem2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="right|center_vertical"
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="#+id/button"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
Then, to get the contents of the row when your button is pressed, you use the button to backtrack to the parent vieew and then get the necessary child views and their contents:
childHolder.section_btn.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
LinearLayout ll = (LinearLayout) v.getParent(); // get the view containing the button
TextView tv1 = (TextView) ll.findViewById(R.id.ListItem1); // get the reference to the first widget
TextView tv2 = (TextView) ll.findViewById(R.id.ListItem2); // get the reference to the second widget
String text1 = tv1.getText.toString(); // Get the contents of the first widget to a string
String text2 = tv2.getText.toString(); // Get the contents of the second widget to a string
}
});
If this isn't what you were looking for clarify your question and I'll take another shot at it.

Categories