Recycle view error that leads to app crash - java

There's a
java.lang.NullPointerException: Attempt to invoke virtual method
'void androidx.recyclerview.widget.RecyclerView.setLayoutManager
(androidx.recyclerview.widget.RecyclerView$LayoutManager)'
on a null object reference and the cause is HomeFragment line 62 and Feed line 100.
I tried to change my to change my recycle view into android.support.v7.widget.RecyclerView and the error
is now feed line 43 but that is the location of my recyclerview.
I also tried to change the fragment line 63 to
getActivity() instead of context.getContext()
This is my Feed class
Line 43:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_feed);
Line 100:
#Override
protected void onStart() {
super.onStart();
}
Fragment
Line 63:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
blog_list = new ArrayList<>();
user_list = new ArrayList<>();
blog_list_view = view.findViewById(R.id.blog_list_view);
blogRecyclerAdapter = new BlogRecyclerAdapter(blog_list, user_list);
blog_list_view.setLayoutManager(new
LinearLayoutManager(container.getContext()));
blog_list_view.setAdapter(blogRecyclerAdapter);
blog_list_view.setHasFixedSize(true);
this is my layout on feed
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Feed">
<androidx.appcompat.widget.Toolbar
android:id="#+id/main_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/authui_colorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.appcompat.widget.Toolbar>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/add_post_btn"
android:layout_width="190dp"
android:layout_height="59dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:clickable="true"
android:focusable="true"
app:layout_constraintBottom_toTopOf="#+id/feedBottomNav"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="#android:drawable/ic_input_add" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/feedBottomNav"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/bottom_menu" />
<FrameLayout
android:id="#+id/feed_container"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#+id/feedBottomNav"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/main_toolbar">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/blog_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
What is the error on my code?

Related

Multi Tab application

I have created multi tabs app in android , But I can't refer to my Xml elements in the class in picture , I have tried solution here findViewById in Fragment but it didn't work for me
here is my xml code
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CountDown">
<EditText
android:id="#+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="101dp"
android:layout_marginTop="50dp"
android:layout_marginEnd="101dp"
android:layout_marginBottom="450dp"
android:autofillHints="time will be here"
android:inputType="time"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.482"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.45"
tools:ignore="Autofill,LabelFor"
tools:text="time" />
</androidx.constraintlayout.widget.ConstraintLayout>
here is my main activity class
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
}
}
here is my main activity xml
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:minHeight="?actionBarSize"
android:padding="#dimen/appbar_padding"
android:text="#string/app_name"
android:textAppearance="#style/TextAppearance.Widget.AppCompat.Toolbar.Title" />
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Try like below code.
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View frag = inflater.inflate(R.layout.count_down, container, false);
EditText time = frag.findViewById(R.id.time);
return frag;
}

Is this possible to change weightSum value programatically using setWeightSum(float)?

I am trying to control weightSum for linear layout from fragment. I wondered if it's possible to do that using setWeightSum(float) method.
I tried to control weight sum in Linear layout which id is header_Linear.
<LinearLayout
android:id="#+id/header_Linear"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:orientation="horizontal"
android:weightSum="8">
<TextView
android:id="#+id/table_0.0"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="visible"
android:background="#drawable/header_bg"/>
<TextView
android:id="#+id/table_0.1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textAlignment="center"
android:gravity="center"
android:text="M"
android:textColor="#color/colorTableItem"
android:visibility="visible"
android:background="#drawable/header_bg"/>
<TextView
android:id="#+id/table_0.2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="T"
android:textColor="#color/colorTableItem"
android:visibility="visible"
android:background="#drawable/header_bg"/>
<TextView
android:id="#+id/table_0.3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="W"
android:textColor="#color/colorTableItem"
android:visibility="visible"
android:background="#drawable/header_bg"/>
<TextView
android:id="#+id/table_0.4"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="T"
android:visibility="visible"
android:textColor="#color/colorTableItem"
android:background="#drawable/header_bg"/>
<TextView
android:id="#+id/table_0.5"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="F"
android:visibility="visible"
android:textColor="#color/colorTableItem"
android:background="#drawable/header_bg"/>
<TextView
android:id="#+id/table_0.6"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="S"
android:textColor="#color/colorTableItem"
android:visibility="visible"
android:background="#drawable/header_bg"/>
<TextView
android:id="#+id/table_0.7"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="S"
android:textColor="#color/sunday_text_color"
android:visibility="visible"
android:background="#drawable/header_bg"/>
</LinearLayout>
This is my fragment that using setWeightSum
public class TimeTableFragment extends Fragment {
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_timetable, container, false);
LinearLayout linearLayout = root.findViewById(R.id.header_Linear);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(Objects.requireNonNull(getContext()));
String header_value = sharedPreferences.getString("Header","0");
Toast.makeText(getContext(),""+header_value,Toast.LENGTH_LONG).show();
if (header_value.equals("0")){
linearLayout.setWeightSum(6);
}
return root;
}
When I start the app it crashes. I'd like to know if it's possible to control weightSum without errors.
Thank you very much
Upate
The reason why I got nullPointException even though I declared Linear Layout using findViewById was due to xmlns:android="http://schemas.android.com/apk/res/android"in Layout.
The View that contains xmlns:android="http://schemas.android.com/apk/res/android" would return null after using findViewById in this situation
public class TimeTableFragment extends Fragment {
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_timetable, container, false);
return root;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
LinearLayout linearLayout = view.findViewById(R.id.header_Linear);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(Objects.requireNonNull(getContext()));
String header_value = sharedPreferences.getString("Header","0");
Toast.makeText(getContext(),""+header_value,Toast.LENGTH_LONG).show();
if (header_value.equals("0")){
linearLayout.setWeightSum(6);
}
}
}

EditText doesn't update its text

EDIT2:
Using
fragTransaction.add(fragment, tag);
instead of
fragTransaction.add(id, fragment);
OR
Removing all Fragments code in MainActivity makes the app works again, for some odd reason.
Getting the text via .getText().toString() returns null/empty when button is pressed.
Tried to manually .setText("something"), it works when .getText().toString() is called but,
when the text is modified, calling .getText().toString() will still return "something".
MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragTransaction = fragmentManager.beginTransaction();
Fragment loginFrag = new LoginFragment();
fragTransaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
fragTransaction.add(R.id.mainFrag, loginFrag);
fragTransaction.commit();
}
LoginFragment.java
public class LoginFragment extends Fragment{
EditText fieldID;
EditText fieldPassword;
Button logButton;
private FirebaseAuth mAuth;
View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.login_menu, container, false);
}
#Override
public void onViewCreated(View v, Bundle savedInstanceState) {
super.onViewCreated(v, savedInstanceState);
mAuth = FirebaseAuth.getInstance();
view = v;
fieldID = v.findViewById(R.id.fieldID);
fieldPassword = v.findViewById(R.id.fieldPassword);
logButton = v.findViewById(R.id.button_login);
logButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
signIn(fieldID.getText().toString(), fieldPassword.getText().toString());
}
});
}
private void signIn(String email, String password) {
System.out.println("Email: " + email);
System.out.println("Pass: " + password);
if(!email.isEmpty() && !password.isEmpty()) {
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d("Auth", "signInWithEmail:success");
FirebaseUser user = mAuth.getCurrentUser();
//updateUI(user);
view.findViewById(R.id.logoMain).setVisibility(View.GONE);
} else {
// If sign in fails, display a message to the user.
Log.w("Auth", "signInWithEmail:failure", task.getException());
//updateUI(null);
}
}
});
}
}
}
Main Activity
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presenter.Activity.MainActivity">
<fragment
android:id="#+id/mainFrag"
android:name="com.raze.mfa.presenter.Fragment.LoginFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Fragment Layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:orientation="vertical">
<ImageView
android:id="#+id/imageView2"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="110dp"
android:adjustViewBounds="true"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/logoMain"
app:layout_constraintVertical_bias="1.0"
app:srcCompat="#drawable/bak"
tools:srcCompat="#drawable/bak" />
<ImageView
android:id="#+id/iconlock"
android:layout_width="43dp"
android:layout_height="43dp"
android:layout_marginStart="8dp"
android:layout_marginTop="28dp"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toStartOf="#+id/fieldPassword"
app:layout_constraintHorizontal_bias="0.523"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/iconuser"
app:srcCompat="#mipmap/lockicon" />
<ImageView
android:id="#+id/iconuser"
android:layout_width="43dp"
android:layout_height="43dp"
android:layout_marginStart="8dp"
android:layout_marginTop="320dp"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toStartOf="#+id/fieldID"
app:layout_constraintHorizontal_bias="0.522"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#mipmap/usericon" />
<Button
android:id="#+id/button_login"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="#string/loginText"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/fieldPassword"
app:layout_constraintVertical_bias="0.188" />
<EditText
android:id="#+id/fieldPassword"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="72dp"
android:autofillHints=""
android:ems="10"
android:hint="#string/password"
android:inputType="textPassword"
android:singleLine="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/fieldID" />
<EditText
android:id="#+id/fieldID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="320dp"
android:layout_marginEnd="72dp"
android:autofillHints=""
android:ems="10"
android:hint="#string/email"
android:inputType="textEmailAddress"
android:singleLine="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/logoMain"
android:layout_width="128dp"
android:layout_height="128dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="108dp"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
app:layout_constraintBottom_toTopOf="#+id/fieldID"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0"
app:srcCompat="#drawable/logoimg" />
<Button
android:id="#+id/button_register"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="#string/register"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/button_login"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
Unrelated:
I've Googled mostly everything but it seems that I haven't understand the basics of using Fragments, Activites, context, Views, and etc.
Ok I see, you are using a <fragment/> tag already in your MainActivity layout, and then you add with the FragmentTransaction a fragment to it.
The transaction is for FrameLayout containers that are empty and take a fragment. When you add the fragment statically through the <fragment/> tag the fragment is already loaded into the screen.
Something weird was happening when you added a new fragment to a fragment tag, maybe it duplicated the fragment and it was reading the one that is behind the actual fragment and it wasn't getting the input from the user.
Read here for the proper use of FragmentTransaction: https://developer.android.com/training/basics/fragments/fragment-ui
Taken from the docs above, see how they use a FrameLayout as the container.
XML:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Java:
public class MainActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState?) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news_articles);
// Check that the activity is using the layout version with
// the fragment_container FrameLayout
if (findViewById(R.id.fragment_container) != null) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
// Create a new Fragment to be placed in the activity layout
HeadlinesFragment firstFragment = new HeadlinesFragment();
// In case this activity was started with special instructions from an
// Intent, pass the Intent's extras to the fragment as arguments
firstFragment.setArguments(getIntent().getExtras());
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
}
}
}

Bottom Sheet Fragment causes error when called the second time

I have a class BottomSheetFragment extends BottomSheetDialogFragment, which contains sub-fragments, and I call it from a fragment.
The problem is that when I call it the second time, my app crashes with Binary XML file line #69: Duplicate id 0x7f090071, tag null, or parent id 0xffffffff with another fragmenterror.
Bottom sheet class:
public class BottomSheetFragment extends BottomSheetDialogFragment {
public BottomSheetFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_bottom_sheet, container, false);
return v;
}
}
In its XML it contains a sub-fragment public class CreateNotesFragment extends android.support.v4.app.Fragment
The BottomSheetFragment class is called in another fragment on button click like this:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_all_works, container, false);
createNew = view.findViewById(R.id.add_file_btn);
createNew.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity mainActivity = (MainActivity)getActivity();
mainActivity.showBottomSheetDialogFragment();
}
});
return view;
}
And here is the method in MainActivity which shows the bottom sheet:
public void showBottomSheetDialogFragment() {
bottomSheetFragment = new BottomSheetFragment();
bottomSheetFragment.show(getSupportFragmentManager(), bottomSheetFragment.getTag());
}
I assume that the CreateNotesFragment no longer exists when I call the BottomSheetFragment for the second time for some reason, but how can I fix it?
Thank you.
Update
Here is the line 69 in fragment_bottom_sheet.xml
<fragment
android:id="#+id/notes_fragment"
android:name="com.app.parsec.secondary_fragments.CreateNotesFragment"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/divider9"
tools:layout="#layout/fragment_create_notes" />
And the whole XML to make you sure that there is no ID duplicates:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".secondary_fragments.BottomSheetFragment"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
android:id="#+id/wasd">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/notes_btn"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#color/colorPrimary"
android:drawableTop="#drawable/ic_note"
android:foreground="?attr/selectableItemBackgroundBorderless"
android:padding="10dp"
android:text="НОТЫ"
app:layout_constraintBottom_toBottomOf="#+id/text_btn"
app:layout_constraintEnd_toStartOf="#+id/text_btn"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/text_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#color/colorAccentDark"
android:drawableTop="#drawable/ic_t"
android:foreground="?attr/selectableItemBackgroundBorderless"
android:padding="10dp"
android:text="ТЕКСТ"
app:layout_constraintEnd_toStartOf="#+id/project_btn"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/notes_btn"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/project_btn"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#color/colorAccentDark"
android:drawableTop="#drawable/ic_shape_1"
android:foreground="?attr/selectableItemBackgroundBorderless"
android:padding="10dp"
android:text="ПРОЕКТ"
app:layout_constraintBottom_toBottomOf="#+id/text_btn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/text_btn"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/divider9"
android:layout_width="0dp"
android:layout_height="3dp"
android:background="#color/colorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/text_btn" />
<fragment
android:id="#+id/notes_fragment"
android:name="com.app.parsec.secondary_fragments.CreateNotesFragment"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/divider9"
tools:layout="#layout/fragment_create_notes" />
</android.support.constraint.ConstraintLayout>
</FrameLayout>
I also noticed that if I remove this fragment from XML, I can open BottomSheetFragment without any crashes, so the problem must be it the sub-fragment.
Solved
The solution is adding fragments into a fragment dynamically, not through XML. So, my BottomSheetFragment now looks like this:
public class BottomSheetFragment extends BottomSheetDialogFragment {
public BottomSheetFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_bottom_sheet, container, false);
getChildFragmentManager().beginTransaction().replace(R.id.fragment_here, new CreateNotesFragment()).commit();
return v;
}
}
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".secondary_fragments.BottomSheetFragment"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
android:id="#+id/wasd">
<android.support.constraint.ConstraintLayout
android:id="#+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/notes_btn"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#color/colorPrimary"
android:drawableTop="#drawable/ic_note"
android:foreground="?attr/selectableItemBackgroundBorderless"
android:padding="10dp"
android:text="НОТЫ"
app:layout_constraintBottom_toBottomOf="#+id/text_btn"
app:layout_constraintEnd_toStartOf="#+id/text_btn"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/text_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#color/colorAccentDark"
android:drawableTop="#drawable/ic_t"
android:foreground="?attr/selectableItemBackgroundBorderless"
android:padding="10dp"
android:text="ТЕКСТ"
app:layout_constraintEnd_toStartOf="#+id/project_btn"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/notes_btn"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/project_btn"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#color/colorAccentDark"
android:drawableTop="#drawable/ic_shape_1"
android:foreground="?attr/selectableItemBackgroundBorderless"
android:padding="10dp"
android:text="ПРОЕКТ"
app:layout_constraintBottom_toBottomOf="#+id/text_btn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/text_btn"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/divider9"
android:layout_width="0dp"
android:layout_height="3dp"
android:background="#color/colorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/text_btn" />
<FrameLayout
android:id="#+id/fragment_here"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/divider9">
</FrameLayout>
</android.support.constraint.ConstraintLayout>
</FrameLayout>
You are trying to open the same fragment. The current fragment should be dismissed. bottomSheetFragment.dismiss(); then bottomSheetFragment.show(getSupportFragmentManager(), tag)
And you can try to give a different tag to fragment.
public void showBottomSheetDialogFragment() {
bottomSheetFragment = new BottomSheetFragment();
bottomSheetFragment.show(getSupportFragmentManager(), bottomSheetFragment.getTag());
}
Edit :
This error occurs on Nested Fragments which has been defined in layout, try to remove your Fragment from XML Layout and replace it with a FrameLayout then instantiate your Fragment dynamically in code.
You are calling fragment tag inside XML file of YourFragment, basically, it's a wrong way to add bottom sheet to fragment. Here is the way you can do it:
Call this method on botton Click:
callToGuideShareDialog();
Inflate the bottom Sheet View inside this method
private void callToGuideShareDialog() {
final View viewBottom = DataBindingUtil.inflate(getLayoutInflater(), R.layout.------, null, false).getRoot();
ImageView imageView = viewBottom.findViewById(R.id.img_size_guide_share);
TextView textViewMsg = viewBottom.findViewById(R.id.----);
viewBottom.findViewById(R.id.-----).setOnClickListener(this);
TextView textViewMeasurement = viewBottom.findViewById(R.id.----);
sheetDialog = new BottomSheetDialog(context);
sheetDialog.setContentView(viewBottom);
viewBottom.post(new Runnable() {
#Override
public void run() {
BottomSheetBehavior mBehavior = BottomSheetBehavior.from((View) viewBottom.getParent());
mBehavior.setPeekHeight(viewBottom.getHeight());
}
});
if (sheetDialog != null)
sheetDialog.show();
}

Android app NPE: Unable to invoke virtual method setOnClickListener on null object

I'm building my first Android app (basic calculator) which consists of one Activity and a single fragment. The layout of the app (display and buttons) are defined in the fragment xml fragment_main.xml and should be inflated on startup. However, the app immediately crashed with a NPE. I'm confused as to whether I should set the click listeners for the calculator buttons in the Activity's onCreate() method, or in the fragment class's onCreateView() method. Code and stack trace below.
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.github.idclark.calculator/com.github.idclark.calculator.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
public class MainActivity extends ActionBarActivity implements OnClickListener {
private TextView mCalculatorDisplay;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new CalculatorFragment())
.commit();
}
mCalculatorDisplay = (TextView) findViewById(R.id.textView);
findViewById(R.id.AC).setOnClickListener(this);
findViewById(R.id.plusminus).setOnClickListener(this);
findViewById(R.id.percent).setOnClickListener(this);
findViewById(R.id.nine).setOnClickListener(this);
findViewById(R.id.eight).setOnClickListener(this);
findViewById(R.id.seven).setOnClickListener(this);
findViewById(R.id.six).setOnClickListener(this);
findViewById(R.id.five).setOnClickListener(this);
findViewById(R.id.four).setOnClickListener(this);
findViewById(R.id.three).setOnClickListener(this);
findViewById(R.id.two).setOnClickListener(this);
findViewById(R.id.one).setOnClickListener(this);
findViewById(R.id.zero).setOnClickListener(this);
findViewById(R.id.div).setOnClickListener(this);
findViewById(R.id.mult).setOnClickListener(this);
findViewById(R.id.plus).setOnClickListener(this);
findViewById(R.id.minus).setOnClickListener(this);
findViewById(R.id.dec).setOnClickListener(this);
findViewById(R.id.equal).setOnClickListener(this);
}
#Override
public void onClick(View v) {
String buttonPressed = ((Button )v).getText().toString();
mCalculatorDisplay.setText(buttonPressed);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class CalculatorFragment extends Fragment {
public CalculatorFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
}
Activity_Main
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:id="#+id/container"
android:layout_width="match_parent" android:layout_height="match_parent"
tools:context=".MainActivity" tools:ignore="MergeRootFrame" />
Fragment_Main
<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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".MainActivity$PlaceholderFragment"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="0"
android:id="#+id/textView"
android:layout_alignEnd="#+id/textView"
android:textSize="65dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/AC"
android:id="#+id/AC"
android:layout_weight="0.25" />
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/plusminus"
android:id="#+id/plusminus"
android:layout_weight="0.25" />
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/percent"
android:id="#+id/percent"
android:layout_weight="0.25" />
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/div"
android:id="#+id/div"
android:layout_weight="0.25" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/nine"
android:id="#+id/nine"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/eight"
android:id="#+id/eight"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/seven"
android:id="#+id/seven"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:id="#+id/mult"
android:text="#string/mult"
android:layout_weight="0.25"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/six"
android:id="#+id/six"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/five"
android:id="#+id/five"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/four"
android:id="#+id/four"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/minus"
android:id="#+id/minus"
android:layout_weight="0.25"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/three"
android:id="#+id/three"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/two"
android:id="#+id/two"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/one"
android:id="#+id/one"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/plus"
android:id="#+id/plus"
android:layout_weight="0.25"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="0.5"
android:text="#string/zero"
android:id="#+id/zero" />
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/dec"
android:id="#+id/dec"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="#string/equal"
android:id="#+id/equal"
android:layout_weight="0.25"/>
</LinearLayout>
The reason for the Null Pointer Exception is that the differents views (Buttons and TextView) you are trying to access are not in your activity's layout file, but in your Fragment's layout file.
setContentView adds all the views in the layout file to the activity.
To fix the NPE, you need to instantiate the views (Buttons and TextView) in your fragment's onCreateView, because the fragment's layout file contains all the views you are going to use.
public class MainActivity extends ActionBarActivity implements OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new CalculatorFragment())
.commit();
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class CalculatorFragment extends Fragment implements OnClickListener {
private TextView mCalculatorDisplay;
public CalculatorFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
mCalculatorDisplay = (TextView) rootView.findViewById(R.id.textView);
rootView.findViewById(R.id.AC).setOnClickListener(this);
rootView.findViewById(R.id.plusminus).setOnClickListener(this);
rootView.findViewById(R.id.percent).setOnClickListener(this);
rootView.findViewById(R.id.nine).setOnClickListener(this);
rootView.findViewById(R.id.eight).setOnClickListener(this);
rootView.findViewById(R.id.seven).setOnClickListener(this);
rootView.findViewById(R.id.six).setOnClickListener(this);
rootView.findViewById(R.id.five).setOnClickListener(this);
rootView.findViewById(R.id.four).setOnClickListener(this);
rootView.findViewById(R.id.three).setOnClickListener(this);
rootView.findViewById(R.id.two).setOnClickListener(this);
rootView.findViewById(R.id.one).setOnClickListener(this);
rootView.findViewById(R.id.zero).setOnClickListener(this);
rootView.findViewById(R.id.div).setOnClickListener(this);
rootView.findViewById(R.id.mult).setOnClickListener(this);
rootView.findViewById(R.id.plus).setOnClickListener(this);
rootView.findViewById(R.id.minus).setOnClickListener(this);
rootView.findViewById(R.id.dec).setOnClickListener(this);
rootView.findViewById(R.id.equal).setOnClickListener(this);
return rootView;
}
#Override
public void onClick(View v) {
String buttonPressed = ((Button )v).getText().toString();
mCalculatorDisplay.setText(buttonPressed);
}
}
}
I hope this helps.
You should override Fragment's onViewCreated() because it is guaranteed that all Views are instantiated.
Create a field in your CalculatorFragment to store the OnClickListener to be assigned to your buttons, you can do it like the following:
public static class CalculatorFragment extends Fragment {
OnClickListener mListener = null;
public CalculatorFragment(OnClickListener listener) {
mListener = listener;
}
//et cetera
In the Activity's onCreate() you must specify the OnClickListener when creating the CalculatorFragment:
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new CalculatorFragment(this))
.commit();
}
In the overriden onViewCreated(), use getView() to get the View returned by onCreateView() so most calls become like
getView().findViewById(R.id.the_id).setOnClickListener(this);
.
See findViewById in fragment android to see how you can use findViewById

Categories