Can anyone explain why my View element (ListView) is null with the following code:
public class NewsFragment extends Fragment {
#InjectView(R.id.news_listView) ListView lv;
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.news_layout, container, false);
ButterKnife.inject(this, view);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (lv == null) {
UIHelper.showAlert("null?");
}
}
}
Am I doing something wrong or is there something wrong with the library, because I pasted the example code to my app to get it working, but it's not working here... Any help is much appreciated!
Have you setup your IDE?
IDE CONFIGURATION
Some IDEs require additional configuration in order to enable
annotation processing.
IntelliJ IDEA — If your project uses an external configuration (like a
Maven pom.xml) then annotation processing should just work. If not,
try manual configuration.
Eclipse — Set up manual configuration
Usually this means that the annotation processor didn't do its work. That might be due to misconfiguration or random problems with the IDE. In my experience, every now and then I had to clean the project and build everything again.
This work for me:
...
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
ButterKnife.bind(this, view);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
...
Related
How are these methods different from each other when trying to get the view?
First:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_a, container, false);
listView = view.findViewById(R.id.listview);
return view;
}
Second:
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
listView = getActivity().findViewById(R.id.listview); }
* some say this is used to get activity views but i used it for getting fragment views(which didn't existed in the activity) and it worked fine.
Third:
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
listView = getView().findViewById(R.id.listview);
}
Three methods are good. In the onCreateView you create the view (!), it's the really first time you can use what you inflated. Then onViewCreated is called with the view you returned in the onCreateView, You can directly use the view given as parameter, it is the same the getView() provides. My advice is to initialise your UI variables here
For onActivityCreated, it is the best place to modify your UI elements. It is called when fragment creation is complete and when fragment is re-attached. There you can use the variables you initialised before, without having to get the activity just for that purpose.
I've noticed every time I create a new blank fragment it gives me some parameters at the top that I find a bit distracting and always delete. I was wondering if there's any way we can set to have these parameters not to appear when a new fragment is created?
Thanks very much.
Create a class and extends it from Fragment. You will get a clean class without any parameters.
public class SampleFragment extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.<xml layout>, container, false);
//Your code
return rootView;
}
}
It is known issue in Android Studio 3.3.1 - 3.4
It is fixed in new android studio version.
in my Fragment.onCreateView(inflater), I keep a reference to a widge:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_shipping, container, false);
...
mMyBtn = (Button) view.findViewById(R.id.mybtn);
So I can use it later:
#Override
public void onResume() {
super.onResume();
...
mMyBtn.setEnabled(false);
Somehow, I get nullpointer in mMyBtn.setEnabled reported in Firebase Crashlytics occasionally (100% Android 8 devices).
Question: did I do it wrong in the wrong lifecycle callback? i.e., instead of keep the widget reference in onCreateView(...), should I do it in onViewCreated(...)? I have been doing this way forever wondering if I am out of dated ...
Any suggestion, to make my code more defensive?
I have updated my Sdk Oreo 8.0 When i come my current fragment to my previous fragment its crash because i am using if (view == null)
if i removed this condition it 'll work fine but have to load again view.
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
if (view == null) {
view = inflater.inflate(R.layout.home_fragement_layout, container, false);
ButterKnife.bind(this, view);
bundle=getArguments();
registrationResponse=(RegistrationResponse)bundle.getSerializable("registerresponse");
setadapter();
hitUserFavouriteOutfitsapi();
swipeRefreshLayout.setOnRefreshListener(this);
}
toolBarTopChangeState =((ToolBarTopChangeState)context);
toolBarTopChangeState.stateChangeToolBarIcon(0);
toolBarTopChangeState.stateChangeToolBarText(getString(R.string.app_name));
return view;
}
Use this code:
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.home_fragement_layout, container, false);
ButterKnife.bind(this, view);
bundle=getArguments();
registrationResponse=(RegistrationResponse)bundle.getSerializable("registerresponse");
setadapter();
hitUserFavouriteOutfitsapi();
swipeRefreshLayout.setOnRefreshListener(this);
toolBarTopChangeState =((ToolBarTopChangeState)context);
toolBarTopChangeState.stateChangeToolBarIcon(0);
toolBarTopChangeState.stateChangeToolBarText(getString(R.string.app_name));
return view;
}
On the lists is a good practice to check if the view is already created and if it's to use it further, but on the activities and fragments you should left the OS to decide when should inflate again the view. You can have a look over android lifecycle to understand better how it's works
it 'll happen because i am adding animation when fragment change and return to back.. This problem facing because of Android 8.0(Oreo) rest os working fine so I removed the animation during fragment change it 'll solved.
I have a view in a fragment. This fragment is within a FrameLayout. I want to animate this view moving outside the fragment borders. However, the view always get clipped when crossing the border. I have tried by setting android:clipChildren="false" and android:clipToPadding="false" to everything, but I can't get it to work.
Is this even possible to do?
I had the similar problem with fragments and put android:clipChildren="false" and android:clipToPadding="false" on all the levels in my hierarchy, but it was still not working. The trick that worked for me was to add this override in my fragment code:
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ViewGroup vg = (ViewGroup) view;
vg.setClipChildren(false);
vg.setClipToPadding(false);
}
Hope this helps...
P.S. the credit should go to this answer
frangulyan You're missing the other bit of code from your credited answer. The below solution worked for me.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
LinearLayout rootView = (LinearLayout) inflater.inflate(R.layout.fragment_main, container, false);
//This can be done in XML
rootView.setClipChildren(false);
rootView.setClipToPadding(false);
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//This is the NoSaveStateFrameLayout - force it to not clip
FrameLayout frameLayout = (FrameLayout) getView();
frameLayout.setClipChildren(false);
frameLayout.setClipToPadding(false);
}
The answers already given by #frangulyan and #Barrie Galitzky were both on the right track, but I had to add this loop to setClipping false for all parents in the hierarchy before it would work properly
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ViewGroup vg = (ViewGroup) view;
while(vg != null) {
vg.setClipChildren(false);
vg.setClipToPadding(false);
vg = vg.getParent() instanceof ViewGroup ? (ViewGroup) vg.getParent() : null;
}
}
I know this is a bit old, and correct answers have been given, but I wanted to add that you can do the same thing as frangulyan does inside onCreateView using the ViewGroup. I.e.:
#Override
public View onCreateView(LayoutInflater, ViewGroup container, Bundle savedInstanceState) {
container.setClipChildren(false);
container.setClipToPadding(false);
// Whatever other setup you like
return View;
}