I have a RecyclerView list with CardViews. I added the following code below to launch an activity (ActActivity) that allows the user to edit the CardView. The setEnabled(false) code is used to keep multiple instances of the activity from opening if the user clicks multiple times in rapid succession on the CardView. I only want one instance of the activity to be open at one time so that the user is only editing the single CardView that they clicked on.
My problem is that when I add the onResume() section to re-set setEnabled() to "true" the app crashes. When I remove the onResume() section then the setEnabled(false) code works correctly by not allowing multiple instances of the activity to open, but the problem is that any doubleclicks on the CardView disable a future single-click to correctly launch the ActActivity.
What am I missing here?
MainActivity.java
public class MainActivity extends AppCompatActivity implements
RecyclerItemClickListener {
lvContact = (RecyclerView) findViewById(R.id.lvContact);
assert lvContact != null;
lvContact.setHasFixedSize(true);
contactListAdapter = new ContactListAdapter(this);
contactListAdapter.setOnItemClickListener(this);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
lvContact.setLayoutManager(layoutManager);
lvContact.setAdapter(contactListAdapter);
...
#Override
public void onItemClick(int position, View view) {
CardView c = (CardView) view;
c.setEnabled(false);
ActActivity.start(this, contactListAdapter.getItem(position));
}
...
Override
protected void onResume() {
super.onResume();
CardView cardView1 = (CardView) findViewById(R.id.singlecard_view1);
cardView1.setEnabled(true);
}
xml file for the RecyclerView:
<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="#FFFFFF"
tools:context="com.v050.MainActivity">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" >
</include>
<LinearLayout
android:id="#+id/todoListLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar"
android:layout_above="#+id/s4"
android:background="#color/background4main"
android:layout_marginTop="6dp"
android:layout_marginStart="6dp"
android:layout_marginLeft="6dp"
android:layout_marginEnd="6dp"
android:layout_marginRight="6dp"
android:layout_marginBottom="6dp"
android:orientation="vertical" >
<android.support.v7.widget.RecyclerView
android:id="#+id/lvContact"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
</LinearLayout>
<TextView
android:id="#+id/s4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="center"
android:textStyle="bold"
android:textColor="#FFFFFF"
android:background="#color/colorPrimary"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingTop="15dp"
android:paddingBottom="15dp"
android:clickable="true" />
</RelativeLayout>
xml file for the CardView:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/singlecard_view1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
card_view:cardBackgroundColor="#android:color/white"
card_view:cardCornerRadius="6dp"
card_view:cardElevation="4dp"
android:foreground="?android:attr/selectableItemBackground"
android:longClickable="true" >
Logcat output does not like the "cardView1.setEnabled(true)" line in the onResume() section:
11-01 23:22:54.814 1399-1399/com.example.v50 E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to resume activity {com.example.v50/com.v050.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2575)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2603)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2089)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.v050.MainActivity.onResume(MainActivity.java:279)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1184)
at android.app.Activity.performResume(Activity.java:5082)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2565)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2603)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2089)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
One proposed answer that works is:
...
#Override
public void onItemClick(int position, final View view) {
view.setEnabled(false);
ActActivity.start(this, contactListAdapter.getItem(position));
view.post(new Runnable() {
#Override
public void run() {
view.setEnabled(true);
}
});
}
How does this compare to answers that use onResume?
Here is problem .....
CardView is in the recycle view and you are trying from the main layout instead of item layout ....
here is your solution for your problem....
create cardview variable as global .......
private CardView cardview;
use it when the item clicked ......
#Override
public void onItemClick(int position, View view) {
cardview = (CardView) view;
cardview.setEnabled(false);
ActActivity.start(this, contactListAdapter.getItem(position));
}
Note:- Always try to declare global variable which have use in many methods .....
EDIT:- try this for the first run in your onResume....
and put condition onResume ....
Override
protected void onResume() {
super.onResume();
if(cardview!=null){
cardview.setEnabled(true);
}
above problem will solve your First Run problem ....
You can initialise the card view in onCreate of activity instead of onResume.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CardView cardView1 = (CardView)findViewById(R.id.singlecard_view1);
}
Override
protected void onResume() {
super.onResume();
cardView1.setEnabled(true);
}
Have you initialized the RecyclerView contact list before following code:
CardView cardView1 = (CardView)findViewById(R.id.singlecard_view1);
If you haven't then the card view will not be created and findViewById(R.id.singlecard_view1);
will return null.
Edited:
I think the view of the RecyclerView's items are not getting initialized untill activity is fully visible which cause findViewById(R.id.singlecard_view1) return null.
But as you have said you just want the edit activity to be started only once.
You can achieve this by-> adding android:launchMode="singleTask" for "ActActivity" in manifest file. OR
->adding FLAG_ACTIVITY_CLEAR_TASK to Intent.
Related
I'm trying to add and show a multiple image views existing in a fragment to another in the same activity by OnItemClickListener on GridView.
I was able to add the first image view but when I add the second one the app crashes.
By the way, I'm adding the image views to a linear layout inside Horizontal Scroll View.
Here is the layout of the first fragment:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/content_fragment_id"
>
<GridView
android:id="#+id/items_id_gridView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:columnWidth="100dp"
android:minHeight="40dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:numColumns="auto_fit"
android:horizontalSpacing="10.0dip"
android:verticalSpacing="10.0dip"
android:cacheColorHint="#00000000"
android:gravity="center_horizontal"
android:requiresFadingEdge="vertical"
/>
</RelativeLayout>
The layout of the second fragment:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<ImageButton
android:id="#+id/play_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/play_36dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:contentDescription="#string/play_button" />
<HorizontalScrollView
android:id="#+id/sentenceBarScrollView"
android:layout_width="fill_parent"
android:layout_height="104dp"
android:layout_toLeftOf="#id/play_button"
android:layout_toStartOf="#id/play_button"
android:padding="1dp"
>
<LinearLayout
android:id="#+id/sentence_bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="2dp"
android:orientation="horizontal"
>
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
The layout of the main activity:
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Home"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
android:id="#+id/sentence_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="vertical">
<fragment
android:id="#+id/sentenceBarFragment"
android:name="ye.com.ebra.contentfragments.SentenceBarFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
</android.support.v7.widget.CardView>
<RelativeLayout
android:id="#+id/content_Layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/sentence_layout"
android:padding="5dp"
>
<!-- put contents fragments here :) -->
</RelativeLayout>
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
the class of the first fragment.
sendItemToSentenceBar connector;
//for retrieving the values of the image stored in database
private Item item;
static ArrayList<Integer> back;
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
back=new ArrayList<>();
DBConnection dbConnection= new DBConnection(getActivity());
GridView gridView=getActivity().findViewById(R.id.items_id_gridView);
final ArrayList<Item> items2=new ArrayList<>(dbConnection.getAll(Cat_id));
ContentAdapter dataAdapter=new ContentAdapter(getActivity(),items2);
gridView.setAdapter(dataAdapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
item=items2.get(position);
if(item.getType().equals("Category"))
{
back.add(Cat_id);
changeFragment(item.getID());
AddNewDialogFragment.Cat_id=item.getID();
}else {
speak(item.getName());
connector.sendData(item);
}
}
});
}
and I'm using an interface to pass the data from OnItemClickListener to the other fragment by "connector.sendData(item);"
Here is the interface:
public interface sendItemToSentenceBar {
// send item to the sentence bar fragment :)
void sendData(Item item);
}
Then in the class of the other fragment
There is the method AddItem(Item item) that should add the image view to the second fragment, the first image view can be added be on the second one the app just crashes :
private ArrayList<Item> items;
private LinearLayout sentenceLayout;
private View itemView;
private ArrayList<View> itemsViews;
View view;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View sentenceBarFragment=inflater.inflate(R.layout.activity_sentence_bar_fragment,container,false);
sentenceLayout = sentenceBarFragment.findViewById(R.id.sentence_bar);
itemView = inflater.inflate(R.layout.activity_item,sentenceLayout,false);
return sentenceBarFragment;
}
public void AddItem(Item item){
TextView name_id = itemView.findViewById(R.id.name_id);
name_id.setText(item.getName());
ImageView image_id = itemView.findViewById(R.id.image_id);
image_id.setImageBitmap(convertByteToBitmap(item.getImage()));
itemsViews.add(itemView);
sentenceLayout.addView(itemsViews.get(0));
items.add(item);
}
Finally the method AddItem(Item item) is used in the class of the main activity that contain both of the fragments:
#Override
public void sendData(Item item) {
FragmentManager fragmentManager=getFragmentManager();
SentenceBarFragment s= (SentenceBarFragment) fragmentManager.findFragmentById(R.id.sentenceBarFragment);
s.AddItem(item);
}
Here the Logcat:
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:3378)
at android.view.ViewGroup.addView(ViewGroup.java:3249)
at android.view.ViewGroup.addView(ViewGroup.java:3194)
at android.view.ViewGroup.addView(ViewGroup.java:3170)
at ye.com.ebra.contentfragments.SentenceBarFragment.AddItem(SentenceBarFragment.java:95)
at ye.com.ebra.contentfragments.Home.sendData(Home.java:129)
at ye.com.ebra.contentfragments.ContentFragment$2.onItemClick(ContentFragment.java:83)
at android.widget.AdapterView.performItemClick(AdapterView.java:298)
at android.widget.AbsListView.performItemClick(AbsListView.java:1086)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:2855)
at android.widget.AbsListView$1.run(AbsListView.java:3529)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
of the Logcat, I could identify those errors:
at ye.com.ebra.contentfragments.SentenceBarFragment.AddItem(SentenceBarFragment.java:95)
which is at the class of the second fragment, in the method AddItem(Item item)
sentenceLayout.addView(itemsViews.get(0));
.
at ye.com.ebra.contentfragments.Home.sendData(Home.java:129)
which is at the class of the main activity, in the used method
sendData(Item item)
s.AddItem(item);
.
at ye.com.ebra.contentfragments.ContentFragment$2.onItemClick(ContentFragment.java:83)
which is in the class of the first fragment, in OnItemClickListener:
connector.sendData(item);
Sorry for the long post, but I'm really stuck here
You appear to be repeatedly modifying and adding the same item_view object inflated in onCreateView(...) method. It strikes me that you need to inflate a new object each time you call "AddItem".
There is also a possible issue with appending views to the itemViews list but repeatedly adding the first view in the list (ie. not the one you just added) .
So SentenceBarFragment might look instead like this:
private ArrayList<Item> items;
private LinearLayout sentenceLayout;
private ArrayList<View> itemsViews;
#Nullable
#Override public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View sentenceBarFragment=inflater.inflate(R.layout.activity_sentence_bar_fragment,container,false);
sentenceLayout = sentenceBarFragment.findViewById(R.id.sentence_bar);
return sentenceBarFragment;
}
public void AddItem(Item item){
// inflate a new view to be added
View itemView = LayoutInflater.from(getActivity()).inflate(R.layout.activity_item,sentenceLayout,false);
TextView name_id = itemView.findViewById(R.id.name_id);
name_id.setText(item.getName());
ImageView image_id = itemView.findViewById(R.id.image_id);
image_id.setImageBitmap(convertByteToBitmap(item.getImage()));
// add the view you just inflated
itemsViews.add(itemView);
sentenceLayout.addView(itemView); // or addView(itemViews.get(itemViews.size()-1))
items.add(item);
}
In my android application, I'm facing a IllegalStateException. I can't reproduce this exception later. This is the stacktrace
Non-fatal Exception: java.lang.IllegalStateException: ScrollView can host only one direct child
at android.widget.ScrollView.addView(ScrollView.java:397)
at android.support.design.widget.BaseTransientBottomBar.showView(BaseTransientBottomBar.java:436)
at android.support.design.widget.BaseTransientBottomBar$1.handleMessage(BaseTransientBottomBar.java:178)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5679)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(NativeStart.java)
Anyone please help me!
I examined the question carefully, and I logically found that it is related to showing Snackbar on a fragment or activity, taken as a reference in another class as global object, when it is invalidated in onStop(), onDestroy() life cycle callback stage respectively:
https://stackoverflow.com/a/52019719/787399
Inside your ScrollView you have to host a child (e.g. a Linear Layout) which at it's time will host all the UI elements from that scrollview. You can't have, for example, 2 textviews added directly to a ScrollView. You need to have something to hold those UI elements inside the scrollview.
In ScrollView you can have only one View (in View I mean TextView, Button and cetera, but ViewGroup is child of View too) or ViewGroup. So if you have multiple Views put them in a proper ViewGroup and it will work fine.
Scrollview can only have one direct child
example:
This is valid-->
ScrollView
LinearLayout
Other Views
....
....
LinearLayout
ScrollView
This is not-->
ScrollView
LinearLayout
Other Views
....
....
LinearLayout
LinearLayout
Other Views
....
....
LinearLayout
ScrollView
I got the same issue. and I have reproduced using the below steps.
Step 1: make you Fragment Or Activity Layout with a parent of Scrollview.
Step 2: show Snackbar in onPause(), onStop(), onDestroy() like belove.
#Override
public void onPause() {
super.onPause();
Snackbar.make(button, "onPause", Snackbar.LENGTH_LONG).show();
}
#Override
public void onStop() {
super.onPause();
Snackbar.make(button, "onStop", Snackbar.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
super.onDestroy();
Snackbar.make(button, "onDestroy", Snackbar.LENGTH_LONG).show();
}
Now run an app and check in logcat. when you click on back button you will get same error mention in question.
Solution:
make a common Snackbar like below.
#Override
public void onPause() {
super.onPause();
showSnackbar("onPause");
}
#Override
public void onStop() {
super.onPause();
showSnackbar("onStop");
}
#Override
public void onDestroy() {
super.onDestroy();
showSnackbar("onDestroy");
}
private void showSnackbar(String message) {
if (isValidContext(getActivity())) {
Snackbar.make(btnConsume, message, Snackbar.LENGTH_LONG).show();
}
}
public static boolean isValidContext(final Context context) {
if (context == null) {
return false;
}
if (context instanceof Activity) {
final Activity activity = (Activity) context;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
return !activity.isDestroyed() && !activity.isFinishing();
} else {
return !activity.isFinishing();
}
}
return true;
}
ScrollView will not accept many child's, Use only one Layout inside ScrollView like LinearLayout, RelativeLayout,FrameLayout or ConstraintLayout(Based on your needs)and then add all your child's.
See this for your reference
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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="wrap_content">
<android.support.constraint.ConstraintLayout 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="wrap_content">
//Add your Views here
</android.support.constraint.ConstraintLayout>
</ScrollView>
Scroll view allow only one child directly like below :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<!--Here scroll view allow only one direct child-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!--Here your other xml code-->
</LinearLayout>
</ScrollView>
</LinearLayout>
Would somebody explain why I'm getting an NPE for my cardView? It makes no sense to me. Here's all relevant code and stack trace:
ACTIVITY hosting the CardView
public class MainScreen extends AppCompatActivity implements TipView.OnValueChangedListener
{
private TipView tipView;
private CardView cardView;
private TextView tipTextView;
private TextView taxTextView;
private TextView splitTextView;
private TextView productTextView;
private TextView totalTextView;
private TextView youPayEachPay;
private ImageButton productEditButton;
private ImageButton dataToggle;
private ProductTotalWindow productTotalWindow;
private double productTotal = 0.0d;
private double currentTip = 0.0d;
private double currentTax = 0.0d;
private int currentSplit = 1;
private NumberFormat currencyFormat;
private String pricesDefaults = "$0.00";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
cardView = (CardView) findViewById(R.id.tipViewCardLayoutContainer).findViewById(R.id.cardViewId);
//NPE is thrown since, obviously the reference points to a null object
cardView.setCardBackgroundColor(Color.RED);
this.tipView = (TipView) findViewById(R.id.tipView);
tipView.setOnValueChangedListener(this);
dataToggle = (ImageButton) findViewById(R.id.dataToggle);
dataToggle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
expandLayout();
}
});
initDataPricesViews();
initProductEditView();
currencyFormat = NumberFormat.getCurrencyInstance();
}
}
XML code for the main layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main_screen"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.bryan.tipease.MainScreen">
<!--
tipview_card_container is the layout hosting my cardview
-->
<include
layout="#layout/tipview_card_container"
android:id="#id/tipViewCardLayoutContainer" />
<FrameLayout
android:layout_alignParentBottom="true"
android:layout_below="#id/tipViewCardLayoutContainer"
android:id="#id/pricesTotalContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/prices_layout" />
</FrameLayout>
</RelativeLayout>
//The cards xml file itself
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
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="wrap_content"
android:id="#id/cardViewId"
app:contentPadding="16dp"
app:cardElevation="16dp"
app:cardBackgroundColor="#color/tipViewCardBackground">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.bryan.tipease.TipView
style="#style/WidgetTipViewStyle"
android:id="#id/tipView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageButton
style="#style/BreakerBarContent"
android:src="#drawable/forkknifefab"
android:id="#id/productDialogLauncher"
android:contentDescription="#string/contentDescForkKnifeImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageButton
style="#style/BreakerBarContent"
android:src="#drawable/toggle_circle"
android:id="#id/dataToggle"
android:contentDescription="#string/contentDescDataToggleImage"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
</android.support.v7.widget.CardView>
Stacktrace
02-23 21:06:55.548 26169-26169/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.bryan.tipease, PID: 26169
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.bryan.tipease/com.example.bryan.tipease.MainScreen}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.CardView.setCardBackgroundColor(int)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2378)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2440)
at android.app.ActivityThread.access$800(ActivityThread.java:162)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1348)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5422)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:914)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.CardView.setCardBackgroundColor(int)' on a null object reference
at com.example.bryan.tipease.MainScreen.onCreate(MainScreen.java:62)
at android.app.Activity.performCreate(Activity.java:6056)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2331)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2440)
at android.app.ActivityThread.access$800(ActivityThread.java:162)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1348)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5422)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:914)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)
This is a weird issue that I've been able to recreate only once. I assumed the problem was with how I was referencing the cardview, with regards to the use of an include tag, however creating a test app to see if I can recreate this problem, there was no issue with my references.
P.S. I've omitted some methods from the activity for sake of brevity, but believe me they're irrelevant to the cause of my issue here.
P.S.S. I can reference any other view in that hierarchy just fine.
As #Mike M. mentioned above in the comments.
First
You do not need to chain your findViewById()'s like you did here:
cardView = (CardView) findViewById(R.id.tipViewCardLayoutContainer).findViewById(R.id.cardViewId);.
The View hierarchy will be searched from the top-down. This means you should search for the android:id="#+id that you want, rather than chaining them.
Second
The id android:id="#id/tipViewCardLayoutContainer" in your <include> overrides the id of your root View, this means your CardView now has the id of tipViewCardLayoutContainer instead of android:id="#id/cardViewId".
All you need to do is remove the id from your <include> and call
CardView cardview = (CardView) findViewById(R.id.cardViewId);
i think id should use +id like this.hope this can help you.
<include
layout="#layout/tipview_card_container"
android:id="#+id/tipViewCardLayoutContainer" />
public void showPopup(int group,int img_index,JSONArray json_ar,View v){
PopupMenu pm=new PopupMenu(EditPhotosActivity.this,v);
pm.getMenuInflater().inflate(R.menu.popup_menu, pm.getMenu());
pm.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
Toast.makeText(getBaseContext(),"You Clicked : " + item.getTitle(),Toast.LENGTH_SHORT).show();
return false;
}
});
pm.show();
}
The showPopup method is being called by an onclick of dynamically created Imagevew. App is getting crashed while executing pm.show().
This is the Error Log.
FATAL EXCEPTION: main
java.lang.RuntimeException: Binary XML file line #17: You must supply a layout_height attribute.
at android.content.res.TypedArray.getLayoutDimension(TypedArray.java:491)
at android.view.ViewGroup$LayoutParams.setBaseAttributes(ViewGroup.java:5709)
at android.view.ViewGroup$MarginLayoutParams.<init>(ViewGroup.java:5850)
at android.widget.FrameLayout$LayoutParams.<init>(FrameLayout.java:610)
at android.widget.FrameLayout.generateLayoutParams(FrameLayout.java:554)
at android.widget.FrameLayout.generateLayoutParams(FrameLayout.java:56)
at android.view.LayoutInflater.inflate(LayoutInflater.java:477)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.support.v7.internal.view.menu.MenuPopupHelper$MenuAdapter.getView(MenuPopupHelper.java:335)
at android.support.v7.internal.view.menu.MenuPopupHelper.measureContentWidth(MenuPopupHelper.java:190)
at android.support.v7.internal.view.menu.MenuPopupHelper.tryShow(MenuPopupHelper.java:128)
at android.support.v7.internal.view.menu.MenuPopupHelper.show(MenuPopupHelper.java:102)
at android.support.v7.widget.PopupMenu.show(PopupMenu.java:108)
at com.newagesmb.version3.EditPhotosActivity$UserAlbum.showPopup(EditPhotosActivity.java:379)
at com.newagesmb.version3.EditPhotosActivity$UserAlbum$1.onClick(EditPhotosActivity.java:246)
at android.view.View.performClick(View.java:4212)
at android.view.View$PerformClick.run(View.java:17476)
at android.os.Handler.handleCallback(Handler.java:800)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5371)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
And this is the Layout
<LinearLayout
android:id="#+id/face_outer"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:layout_weight=".2">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/darker_gray">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/photo_face"
android:paddingLeft="10dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:src="#drawable/btn_add_photo"
android:textColor="#android:color/white"
android:padding="3dp"
android:id="#+id/add_face"/>
</RelativeLayout>
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:id="#+id/face_scroll"
android:background="#android:color/white"
android:padding="2dp">
<LinearLayout
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:id="#+id/face_linear"
android:orientation="horizontal" >
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
/This is the piece of code from where showPopup method is called/
LinearLayout ll_face=(LinearLayout) findViewById(R.id.face_linear);
// The above line of code is written inside onCreate method
ImageView imageView1=new ImageView(EditPhotosActivity.this);
imageView1.setPadding(3,3, 3,3);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
imageView1.setLayoutParams(layoutParams);
ll_face.addView(imageView1);
img_loader.DisplayImage(tmp_json_array.getJSONObject(j).getString("thumb_image"),imageView1);
final int group=i;
final int img_index=j;
imageView1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showPopup(group,img_index,json_ar,v);
}
});
Make sure your have set right theme. android.support.v7.widget.PopupMenu expect the Application to have AppCompat theme, else it will throw exception when you try to show the PopupMenu
android:theme="#style/Theme.AppCompat"
But, android.widget.PopupMenu will work without this theme.
Although I was using AppCompat Theme, but I still had the same problem
I found out that problem is in the declaration of the PopupMenu, and the context I am passing to it.
I was using it like that:
PopupMenu popup = new PopupMenu(getApplicationContext(),v)
But it should be like this:
PopupMenu popup = new PopupMenu(MyActivity.this,v)
I had the same issue when creating PopupMenu. I determined that PopupMenu was using:
import android.support.v7.widget.PopupMenu;
The fix was to edit it to:
import android.widget.PopupMenu;
I think this might be happening because you are using getBaseContext() at Toast.makeText . Try using getApplictaionContext() or EditPhotosActivity.this
I have a DialogFragment defined as inner class in my Fragment class. On Orientation Change even the following exception is poped up:
Caused by: android.app.Fragment$InstantiationException: Unable to instantiate fragment my.package.fragments.ImportFragment$FailedImportDialog: make sure class name exists, is public, and has an empty constructor that is public
at android.app.Fragment.instantiate(Fragment.java:585)
at android.app.FragmentState.instantiate(Fragment.java:96)
at android.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1682)
at android.app.Activity.onCreate(Activity.java:861)
at my.package.activities.ImportActivity.onCreate(ImportActivity.java:8)
at android.app.Activity.performCreate(Activity.java:4465)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
... 12 more
Caused by: java.lang.InstantiationException: can't instantiate class my.package.fragments.ImportFragment$FailedImportDialog; no empty constructor
at java.lang.Class.newInstanceImpl(Native Method)
at java.lang.Class.newInstance(Class.java:1319)
at android.app.Fragment.instantiate(Fragment.java:574)
But I do have public constructor:
class FailedImportDialog extends DialogFragment {
private EditText edtPassword;
private Button button;
public FailedImportDialog() { // Here it is!
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.another_password_dialog, container, false);
edtPassword = (EditText) v.findViewById(R.id.another_password_dialog_et_password);
getDialog().setTitle(R.string.failed_to_decrypt);
Button button = (Button) v.findViewById(R.id.another_password_dialog_btn_ok);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
});
return v;
}
}
Here is xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="10dp">
<TextView android:id="#+id/another_password_dialog_tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/what_password_did_you_use">
</TextView>
<EditText android:id="#+id/another_password_dialog_et_password"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:inputType="textPassword">
<requestFocus>
</requestFocus>
</EditText>
<Button android:id="#+id/another_password_dialog_btn_ok"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="OK">
</Button>
</LinearLayout>
Do you guys know why this exception happens? Thank you!
UPDATE: If I move a class to a separate file there is no such an exception, everything goes smoothly. So the question is - why this exception happens when DialogFragment is an inner class?
Calling setRetainInstance(true) will cause the FragmentManager to save your actual Fragment instance. Instead of destroying and recreating the Fragment, it will just pass the same one along to the new Activity.
try making the inner class static:
public static class FailedImportDialog extends DialogFragment
I will post more explanation about this in a while. In the meantime, try this and let me know if it works.
Define your inner class like this:
public class FailedImportDialog extends DialogFragment {
....
}
With the public notation.
Because, this is what your LogCat says:
Caused by: android.app.Fragment$InstantiationException: Unable to instantiate fragment
my.package.fragments.ImportFragment$FailedImportDialog: make sure class name exists
is public, and has an empty constructor that is public