I have come across a problem where the screen of my Android device(Moto G2) gets blurred on click of a specific button in my app. This event happens occasionally and not everytime I click this button.
This scenario is not happening on few other devices (like LG G3) in which I have tested the app for some time.
I couldnot find anything related or useful in the Logs either.
Just to add, the Log in button which is posing this issue is in a view of a fragment attached.
A screenshot of the scenario :
Adding code in the Activity's onCreate() where it adds the Fragments :
if (savedInstanceState == null) {
facebookLoginBtnFragment = new FacebookLoginBtnFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.container, facebookLoginBtnFragment).commit();
googleLoginBtnFragment = new GoogleLoginBtnFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.container2, googleLoginBtnFragment).commit();
} else {
facebookLoginBtnFragment = (FacebookLoginBtnFragment)getSupportFragmentManager().findFragmentById(R.id.container);
googleLoginBtnFragment = (GoogleLoginBtnFragment)getSupportFragmentManager().findFragmentById(R.id.container2);
}
Below is the code of onCreateView() of the Google + fragment :
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_gplusloginbtns, container, false);
gplusButton = (SignInButton)rootView.findViewById(R.id.GPlus_Sign_in_button); gplusButton.setOnClickListener(this);
setGooglePlusButtonText(gplusButton, "Log in with Google");
rootView.findViewById(R.id.GPlus_sign_out_button).setOnClickListener(this);
if (mActivity.getClass().toString().contains("ShowProfile_act")) {
rootView.findViewById(R.id.GPlus_Sign_in_button).setVisibility(View.GONE);
} mConnectionProgressDialog = new ProgressDialog(getActivity()); mConnectionProgressDialog.setMessage("Logging in...");
return rootView;
}
Below is the code for setGooglePlusButtonText() method :
private void setGooglePlusButtonText(SignInButton signInButton, String buttonText) {
// Find the TextView that is inside of the SignInButton and set its text
for (int i = 0; i < signInButton.getChildCount(); i++) {
View v = signInButton.getChildAt(i);
if (v instanceof TextView) {
TextView tv = (TextView) v;
tv.setText(buttonText);
return;
}
}
}
-->The others methods of the fragment deal with connection maintenance part with the Google+ API.I assume they might not be relevant
Any suggestions, advices on the cause and how to avoid such scenarios would be helpful.
Related
Im working on loading data from Firebase Realtime Database by ViewModel. In my layout I have progress bar and recyclerview. Things work perfecly when i need to load my data first, when I click on button fragment opens instantly, progress bar is running and when data loads it stop running and recyclerview shows up. But, when i go into that fragment again (Data is already loaded), no progress bar is shown (which is okay), but it takes about second to comming that switch, which is significantly slower than first behaviour that i described.
So, I am wondering what is making it to wait that long in second scenario and how can I override it, so my fragment shows up first and then shows up recyclerview?
I have already tried using viewstub and dummy views but nothing seems to work..
My CategoryFragment
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
homeViewModel = new ViewModelProvider(requireActivity()).get(MenuViewModel.class);
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(root == null || fragmentState == STATE_STARTUP)
{
binding = FragmentCategoryRecyclerBinding.inflate(inflater, container, false);
root = binding.getRoot();
binding.categoryRecycler.setHasFixedSize(true);
binding.categoryRecycler.setLayoutManager(new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false));
layoutAnimationController = AnimationUtils.loadLayoutAnimation(getContext(), R.anim.layout_item_fade_scale);
myFoodListAdapter = new MyFoodListAdapter(getContext(), foodModelList, String.valueOf(menuIndex), String.valueOf(categoryIndex));
binding.categoryRecycler.setAdapter(myFoodListAdapter);
}
else
binding = FragmentCategoryRecyclerBinding.bind(root);
return root;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
homeViewModel.getMessageError().observe(getViewLifecycleOwner(), s -> Toast.makeText(getContext(), "" + s, Toast.LENGTH_SHORT).show());
homeViewModel.getMenuList(restaurantId).observe(getViewLifecycleOwner(), menuModels -> {
if(fragmentState == STATE_STARTUP || fragmentState == STATE_SEARCHING)
{
binding.categoryRecycler.setLayoutAnimation(layoutAnimationController);
myFoodListAdapter.setFoodModelList(menuModels.get(menuIndex).getCategories().get(categoryIndex).getItems());
binding.progressBar.hide();
binding.categoryRecycler.setVisibility(View.VISIBLE);
fragmentState = STATE_INITIALIZED;
if(foodModelList.isEmpty())
foodModelList = menuModels.get(menuIndex).getCategories().get(categoryIndex).getItems();
myFoodListAdapter.notifyDataSetChanged();
}
});
}
#Override
public void onDestroyView() {
binding = null;
super.onDestroyView();
}
Sorry for the late reply
Use viewmodel or androidviewmodel in onstart instead on create
I'm using 2 EditText next to each other, the left one gains focus on the fragment startup, I want to give the right one focus I've tried to call requestFocus() on the right EditText but it's not working
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.sandwich_fragment,container, false);
sandwichNameEditText = view.findViewById(R.id.sandwich_name_edit_text);
sandwichPriceEditText = view.findViewById(R.id.sandwich_price_edit_text);
insertSandwichImageView = view.findViewById(R.id.insert_sandwich_btn);
sandwichListView = view.findViewById(R.id.sandwich_list);
dbHandler = new DBHandler(getContext(),null);
sandwichArrayList = dbHandler.getSandwiches();
final SandwichListAdapter adpater = new SandwichListAdapter(getContext(),
R.layout.sandwich_item, sandwichArrayList);
sandwichListView.setAdapter(adpater);
insertSandwichImageView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if(sandwichNameEditText.getText().toString().equals("") || sandwichPriceEditText.getText().toString().equals("")){
Toast.makeText(getContext(),"No empty strings.", Toast.LENGTH_SHORT).show();
return;
}
Sandwich sandwich = new Sandwich(sandwichNameEditText.getText().toString(),
Double.parseDouble(sandwichPriceEditText.getText().toString()));
dbHandler.addSandwich(sandwich);
adpater.add(sandwich);
sandwichNameEditText.setText("");
sandwichPriceEditText.setText("");
sandwichNameEditText.requestFocus(); // working here
}
});
sandwichNameEditText.requestFocus(); // not working here
return view;
Try to call requestFocus in the onViewCreated method.
The request for focus is something you should do once your View is created.
You can find some insights about the difference between onCreateView and onViewCreated methods for a Fragment here.
That said, you should move your view elements initialisations in the onViewCreated as well, since they're something you want to do after the view is created and not while it's being created. Just leave the inflate logic there, and do the other logic once the View is there.
I have a problem, whenever i try to add an eventhandler to a button i get a null reference exception, i am trying to create a popup window with a DialogFragment, where inside it im calling the view PopUpWindow wich will show up on screen, but when i try to access the buttons by id and to assign them eventhandlers for example:
Button btnCopyText = dp.view.FindViewById<Button>(Resource.Id.btnCopyText);
btnCopyText.Click += BtnCopyText_Click;
then i get a null reference exception, can anyone help me, below is the necessary code.
class dialog_Popup:DialogFragment
{
public View view;
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
base.OnCreateView(inflater, container, savedInstanceState);
view = inflater.Inflate(Resource.Layout.PopupWindow, container, false);
return view;
}
public override void OnActivityCreated(Bundle savedInstanceState)
{
Dialog.Window.RequestFeature(WindowFeatures.NoTitle);
base.OnActivityCreated(savedInstanceState);
}
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
//some code
}
public string itemclicked;
dialog_Popup dp;
private void Lv_ItemLongClick(object sender, AdapterView.ItemLongClickEventArgs e)
{
//View popUpView = LayoutInflater.Inflate(Resource.Layout.PopupWindow,
//null); // inflating popup layout
Button height = FindViewById<Button>(Resource.Id.btnCopyText);
//Then: change the width of the button
FragmentTransaction transaction = FragmentManager.BeginTransaction();
dp = new dialog_Popup();
dp.Show(transaction,"Popup");
itemclicked = lv.GetItemAtPosition(e.Position).ToString();
Button btnCopyText = dp.view.FindViewById<Button>(Resource.Id.btnCopyText);
btnCopyText.Click += BtnCopyText_Click;
Button btnSaveCurrentAya = dp.view.FindViewById<Button>(Resource.Id.btnSaveCurrentAya);
btnSaveCurrentAya.Click += BtnSaveCurrentAya_Click;
Button btnsavingsAya = dp.view.FindViewById<Button>(Resource.Id.savingsAya);
btnsavingsAya.Click += BtnsavingsAya_Click;*
Button btnShareFB = dp.view.FindViewById<Button>(Resource.Id.fbShare);
btnShareFB.Click += BtnShareFB_Click;
}
}
There are several reasons why a NullReferenceException can occur with FindViewById:
The layout does not contain the id -> check that the correct layout and id is inflated/ referenced
The type like Button is incorrect
In your case, check that dp and dp.view is not null.
One thing to mention here is, that it is not the best implementation to reference the control of a fragment in you main view. A fragment is something that should be able to life on her own. So I see two ways of implementing your desired behavior:
1) The fragment gets an event and you listen to that. This means your main view will contain the logic to save something.
2) The logic moves into the fragment.
My users should be able to change (using preferences) how the interface looks like (visually enabling and disabling certain layouts dynamically) in my app.
I'm working with the v4 ViewPager (PagerTabStrip to be exact) and am trying to change this in the onResume() method, right after the user closes the "settings menu" to return to the app.
I can change variables this way, but cannot seem to change anything layoutwise (I used to work with TabHosts, where this worked perfectly). If I call this method in the onCreateView() method, everything works fine, but I don't want my users to force close the app before any changes can be visible.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = null;
vContainer = container; // global variable
switch (mCurrentPage) {
case 1:
v = inflater.inflate(R.layout.lifepoints_layout,
container, false);
// irrelevant code
InputStyleType = (LinearLayout) v
.findViewById(R.id.llInputEditText);
InputStyleButtons = (TableLayout) v
.findViewById(R.id.tlInputButtons);
InitializePreferences(); // <- this method
break;
case 2:
// irrelevant code
break;
default:
break;
}
return v;
}
This works perfectly, as it should. However, when the code gets called via the onResume(), the program crashes!
#Override
public void onResume() {
super.onResume();
if (isPaused)
InitializePreferences();
isPaused = false;
}
This is the method itself:
public void InitializePreferences() {
SharedPreferences getPreferences = PreferenceManager
.getDefaultSharedPreferences(getActivity().getBaseContext());
prefInput = getPreferences.getBoolean("pref_input", true);
prefFb = getPreferences.getBoolean("pref_fb", false);
if (prefInput) {
InputStyleType.setVisibility(View.GONE);
InputStyleButtons.setVisibility(View.VISIBLE);
} else {
InputStyleButtons.setVisibility(View.GONE);
InputStyleType.setVisibility(View.VISIBLE);
}
}
I've tried a lot, but nothing seems to work. It seems I cannot change anything layoutwise unless it's directly called from the onCreateView, which doesn't seem right.
EDIT 1
I've analysed my method completely, it gets called correctly and I've tested with some variables. Everything works fine until I'm trying to change something that is visible to the user (toasts work perfectly fine).
EDIT 3
Deleted Edit 2 and this is where my code stands at the moment. It's still not working, and it's actually a bit of a mess. I do think the answer isn't far off.
public void InitializePreferences() {
SharedPreferences getPreferences = PreferenceManager
.getDefaultSharedPreferences(getActivity().getBaseContext());
prefInput = getPreferences.getBoolean("pref_input", true);
prefFb = getPreferences.getBoolean("pref_fb", false);
if (isPaused) {
getActivity().getWindow().getDecorView().invalidate();
LayoutInflater inflater = (LayoutInflater) getActivity()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.lifepoints_layout, vContainer,
false);
InputStyleType = (LinearLayout) v.findViewById(R.id.llInputEditText);
InputStyleButtons = (TableLayout) v
.findViewById(R.id.tlInputButtons);
InputStyleType.invalidate();
InputStyleButtons.invalidate();
}
if (prefInput) {
InputStyleType.setVisibility(View.GONE);
InputStyleButtons.setVisibility(View.VISIBLE);
} else {
InputStyleButtons.setVisibility(View.GONE);
InputStyleType.setVisibility(View.VISIBLE);
}
}
I think you need to invalidate your views. Try adding InputStyleType.invalidate() and InputStyleButtons.invalidate() to the InitializePreferences method. You might need to also invalidate the view parent(s) that contain InputStyleType and InputStyleButtons.
EDIT: Try this in the onResume() callback:
LayoutInflater inflater = getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.lifepoints_layout,
container_2, false);
To make this work create a global ViewGroup variable and set it's value to the value of container in the onCreateView callback.
container_2 = container;
I've integrated a map fragment (Android Maps Api V2) in my app, and this works fine as shown in this pic :
but when soft keybord is shown, map is slided to top and becomes blank as shown in the following pic :
I also must say that this phenomenon accurs on a galaxy S (2.3.3) not in galaxy SIII and even not in galaxy Y, is it a performance problem or bug or am I missing anything ?
Please help if you ever have encountred this problem..
Thanks.
You could try this:
public class MyMapFragment extends SupportMapFragment() {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
setMapTransparent((ViewGroup) view);
return view;
};
private void setMapTransparent(ViewGroup group) {
int childCount = group.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = group.getChildAt(i);
if (child instanceof ViewGroup) {
setMapTransparent((ViewGroup) child);
} else if (child instanceof SurfaceView) {
child.setBackgroundColor(0x00000000);
}
}
}
// ...
};
Instead of using the mapFragment provided by google, use this one. It fixed the same issue for me, but it was doing it on a sliding menu.
Credits to: https://github.com/jfeinstein10/SlidingMenu/issues/168#issuecomment-11834105