Random ClassCastExceptions to apparently random views using findViewById - android

I don’t consider myself an experienced developer, but I can say that I’m experienced enough to avoid ClassCastExceptions on views: I know which view is linked to which id in my layout.
What’s happening is that I’m getting silly crashes along the line of:
TextView v = (TextView) view.findViewById(R.id.my_text_view);
ClassCastException: cannot cast AppCompatImageView to TextView
in different parts of the app, but not in a reproducible way (it doesn’t happen every time I do that particular action). This is driving me crazy!
Examples
// IN A AppCompatDialogFragment
// R.layout.sheet_menu is a frame with only two childs:
// a TextView and a RecyclerView.
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.sheet_menu, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
titleView = (TextView) view.findViewById(R.id.menu_sheet_title);
list = (RecyclerView) view.findViewById(R.id.menu_sheet_list);
// CLASSCASTEXCEPTION! Cannot cast AppCompatTextView to RecyclerView!
}
And another:
// IN A RECYCLERVIEW ADAPTER
// Inflating the view holder layout with
// View.inflate(mContext, R.layout.editable_story, null);
private class EditableStoryHolder extends PrimaryHolder {
public EditableStoryHolder(View itemView) {
super(itemView);
...
likes = (TextView) itemView.findViewById(R.id.likes_count);
// CLASSCASTEXCEPTION! Cannot cast AppCompatImageView to TextView
}
Double Checked
I’m never explicitly calling removeView or anything else
I am importing the right package R class
The ids I’m using are unique in all the project, and I’m pretty sure they are not used inside any of my dependencies
So, what’s happening? Why does findViewById return the wrong child? I’m testing on API23, using support libraries v. 23.2.1. This is a pretty new issue. Something wrong with the appcompat layout inflater?

Sometimes the generated R file becomes out of sync (not sure why but I experience this issue often)
Simply clean the project by selecting Build -> Clean Project
This should regenerate the R files and solve the issue, you may have to clean the project everytime you add a new view to a layout

Did you introduce library that will affect the LayoutInflater or related factories? Make sure the inflater create a correct view. I think you can debug into LayoutInflater.java to make sure everything works correctly.

Related

How onCreateView works

I started a TabLayout Activity, which includes the following code to create the fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_find, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
I've read the official documentation and still unsure how it works. If somebody could explain in detail how each part here is working that would be great.
Edit: Mainly referring to View rootView = inflater.inflate(R.layout.fragment_find, container, false); what each of these 3 parameters are doing and how inflater.inflate() is working here.
OK, here we go.
The process of inflating is simply creating your view explicitly instead of doing this implicitly, this is by using this:
public void onCreate(){
setContentView(R.layout.your_layout);
}
Compare with this question.
Now with the arguments. Compare this with this section.
R.layout.fragment_find returns ID of a fragment used somewhere in the code. R is a dynamic android class used for manipulating some of your app's resources such as views, strings etc. Compare.
container is a root from some ViewGroup. So you hgave a group of, say, buttons doing common things (for example choosing some colour in your application), and they all have same parent, in your case called a container.
attachToRoot is the last argument. According to docs:
If false, root is only used to create the correct subclass of LayoutParams for the root view in the XML.
So it is not attached to the parent we talked about in last point. Compare here.
I hope this helped.
onCreateView():
After the onCreate() is called (in the Fragment), the Fragment's onCreateView() is called. You can assign your View variables and do any graphical initialisations. You are expected to return a View from this method, and this is the main UI view, but if your Fragment does not use any layouts or graphics, you can return null (happens by default if you don't override).
Here, it's a method of the lifecycle for Fragment.

Android: How to use PDFViewer with Fragments

I have a requirement where I need to display PDF file within my Android app. I have used PDFViewer.jar to do so in some of my Activities, which is explained here https://github.com/jblough/Android-Pdf-Viewer-Library . Now I am stuck up with displaying PDF file inside a Fragment. But PDFViewer.jar has been limited to Activity. I have seen the source code of PDFViewer.jar and am unable to convert it for Fragment. Can anyone help me please.
Thanks
You should take, PdfViewerActivity.java (https://github.com/jblough/Android-Pdf-Viewer-Library/blob/master/src/net/sf/andpdf/pdfviewer/PdfViewerActivity.java), rename it to PdfViewerFragment.java.
Change extends Activity to extends Fragment in Android Studio, and correct each red line.
Also, don't forget to import the rest of the project (or you'll have missing classes)
You should especially change each need of Context (this) by getActivity() and findViewById() by getView().findViewById(R.id.foo).
Surely, it won't be enough, but it's a good place to start.
This is load PDF in fragment use PDFViewer
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_keluarga, container, false);
pdfView = (PDFView) v.findViewById(R.id.keluargaPdf);
pdfView.fromAsset("tiga.pdf").load();
// Inflate the layout for this fragment
return v;
}

section_label cannot be resolved (R.id.section_label)

this is my first post so I apologise if it is in the wrong place or if it has been answered. I am a beginner but have worked through most of the tutorials on Google's development site.
I decided to experiment with http://developer.android.com/guide/topics/ui/controls/checkbox.html because it is closer to what I want to create but I am coming up with only one error. So being a beginner maybe I have missed something (although I am following to link from Google).
Here is the section that has the error...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
On the 5th line, R.id.section_label is the issues. Thanks for any help you can give me :)
Try:
Hit ctrl+shift+o to import anything if you are missing it. Make sure that the Id of the view that you are changing matches the actual Id. So go to the activity XML file and find the label and make sure it has the
#+id/section_label
If it's a problem with "R", that's a bug in Eclipse where the java files that should be auto-generated aren't being generated and you have to close the project and then reopen and clean it.

The method findViewById(int) is undefined for the type

I get the error
The method findViewById(int) is undefined for the type PM_section
when trying to implement my Expandable ListView. I am sure this is a common error, but I am having trouble finding a solution. I am attempting to learn fragments and such, and it has been an uphill battle ever since I started. I have done a fair bit of searching, and found a lot of results, that don't seem to help me in my case.
If someone could give me any insight, or point me in the right direction I would greatly appreciate it.
My small test class is below
public class PM_section extends Fragment {
// CustomExpListView custExpListView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
View V = inflater.inflate(R.layout.fragment_pm_section_test, container, false);
CustomExpListView custExpListView = (CustomExpListView)
this.findViewById(R.id.ExpandableListView01);
return V;
}// end on create
}
The CustomExpListView class was pretty much copy, pasted from the Android Sample Projects, and is happy and has no problems.
Thanks you for helping me out.
If R.id.ExpandableListView01 is part of R.layout.fragment_pm_section_test, then replace this with V.
CustomExpListView custExpListView = (CustomExpListView)
V.findViewById(R.id.ExpandableListView01);
Fragments do not have a findViewById() method. You need to use your inflated View instead to get everything from your layout.
Also consider using Java naming conventions. Variables start with lowercase letters while Classes start with Uppercase letters.
Simply get the fragment's root view by calling getView() and then call findViewById() method:
getView().findViewById(R.id.ExpandableListView01);
Without it you will not be able to use findViewById() as Fragment class doesn't itself have such method.

Demo Master Detail View - Detail Fragment Change Content

Context: I'm using the Wizard with in Eclipse and ADT to get a master detail view framework.
I have a good understanding of the fragments need to sit with in an activity and that with in a view etc how ever looking at the example I'm trying to work out how best to change it so I can start developing a app my self.
Is the 'dummy' content view actually needed ? All it seems to contain is the menu options ?
The questions I have is does any one know how the detail view is created ? From what I am reading the app is just taking the item ID and placing it in the detail view as text ?
Extract from Itemdetailfragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_item_detail, container, false);
if (mItem != null) {
((TextView) rootView.findViewById(R.id.item_detail)).setText(mItem.content);
}
return rootView;
}
Is the best way to re do a detail fragment for each new screen I need and place some logic behind that or code the existing one to look at the menu option selected and display the right code ?
Finally is this the best example to start working with ?
The questions I have is does any one know how the detail view is
created ? From what I am reading the app is just taking the item ID
and placing it in the detail view as text ?
Yes, that is exactly what it is doing. This is done in the detail fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_team_detail,
container, false);
// Show the dummy content as text in a TextView.
if (mItem != null) {
((TextView) rootView.findViewById(R.id.team_detail))
.setText(mItem.content);
}
return rootView;
}
You need to change it to get whatever data you need from whatever source you want to use (website, database or change the hard coded values
If you look at the DummyContent.java class you will see the comment
/** TODO: Replace all
uses of this class before publishing your app. */
Basically you should re-write this class to get the data that you want
I've actually added action bar sherlock to make this compatible with api 8 with a little help from this question Two questions about Master/Detail Flow Template
There is a hint that you could use ContentLoader in conjunction with a ContentProvider to get your data from another source such as a database or a web service

Categories

Resources