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;
Related
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.
Hello fellow developers!
i'll keep this as simple and short as I can,
I have a fragment, and in my onCreateView I am sometimes giving it different layouts depend on my status.
is there any way of knowing on which layout I am?
code below:
my onCreateView:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view;
if (programState) {
view = inflater.inflate(R.layout.fragment_home_program_on, container, false);
} else {
view = inflater.inflate(R.layout.fragment_home, container, false);
}
findViews(view);
setupViews();
return view;
}
basically, my "findViews" method gets that View, and I was wondering if there's a way to know which layout i am on with a switch statement for example or something like that.. like this :
private void findViews(View mainView) {
switch(mainView) {
case R.layout.fragment_home:
//do work
break;
case R.layout.fragment_home_program_on:
//do work
break;
}
}
I am trying to do something like that with no success.. all i get is errors and such, is there a way to do that?
thanks a lot in advance
is there any way of knowing on which layout I am?
Sure. Check programState. You are already doing that to determine which layout to load, so use that to determine which layout you loaded.
I was wondering if there's a way to know which layout i am
Use if (programState), the same way you did in onCreateView().
Beyond that, a widget has no idea what layout resource it came from. So, somewhere, you need to track that information yourself, and you seem to be doing so already in programState.
try mainView.getId() in switch. I think that's what you need
Change your method to something like this:
private void findViews(View mainView) {
int viewId = mainView.getId();
switch(viewId) {
case R.id.firstViewId:
//do work
break;
case R.id.secondViewId:
//do work
break;
}
}
If you have various Views and you need to differentiate them - try adding tags to them.
1 - If you are going to have more then one tag type - create keys for them.
And use mainView.setTag(TAG_TYPE_ID_1, 10011) (many tags for a view) rather than mainView.setTag(10011) (only one tag for a view).
In this case TAG_TYPE_ID_1 may be your constant field. It must be initialized with id of some Resource. For example public static final int TAG_TYPE_ID_1 = R.layout.my_frame_layout;
Also consider placing int viewId = (int) mainView.getTag() into try/catch because you can get ClassCastException if you will put there a String for example but will try to get int.
But for this example we assume you don't need lots of tags and you know that you have only int as a tag.
2 - Set tag into the view in onCreateview() method in your fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view;
if (programState) {
view = inflater.inflate(R.layout.fragment_home_program_on, container, false);
view.setTag(1011);
} else {
view = inflater.inflate(R.layout.fragment_home, container, false);
view.setTag(1012);
}
findViews(view);
setupViews();
return view;
}
3 - Then read the tag value in your view and decide what to do
private void findViews(View mainView) {
if(mainView.getTag() == null)
return;
switch((int) mainView.getTag()) {
case 1011:
//do work
break;
case 1012:
//do work
break;
}
}
NOTE: don't forget that here switch((int) mainView.getTag()) you can get ClassCastException or NullPointerException if tag will be different type or null
Also int codes like 1011, 1012 etc. is better to store as a constant fields
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.
I have a some fragment in my PageViewer.
In the main fragment, I would like to show a component ( TextView or imageView) if there is no connection.
In the code below, I can reach my textview, but I cannot get them disapperead.
public class MainFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.main, container, false);
// RelativeLayout mainLayout = (RelativeLayout)findViewById(R.layout.main);
TextView TxtIsNotConnected = (TextView) layout.findViewById(R.id.isNotConnected);
TextView TxtIsConnected = (TextView) layout.findViewById(R.id.isConnected);
// String text = TxtIsNotConnected.getText().toString(); // This is a test which works, return the text o my textview.
boolean isConnected = ConnectivityUtils.isConnected(getActivity()); // This Works fine
if (!isConnected) TxtIsNotConnected.setVisibility(View.VISIBLE); // NOT WORKING
else TxtIsConnected.setVisibility(View.VISIBLE); // NOT WORKING
return inflater.inflate(R.layout.main, container, false);
}
How should I do???
To make your TextView visible
yourTextView.setVisibility(View.VISIBLE);
To make Invisible
yourTextView.setVisibility(View.GONE);
From your code it seems that you have to keep one view visible and another invisible. So, please try this
if (!isConnected) {
TxtIsNotConnected.setVisibility(View.VISIBLE);
TxtIsConnected.setVisibility(View.GONE);
} else {
TxtIsConnected.setVisibility(View.VISIBLE);
TxtIsNotConnected.setVisibility(View.GONE);
}
Hope it helps...
Edit :
Well, your code is correct about visibility but you have made a silly mistake that's why it seems that your code is not working. Look at the first line and last line of your onCreateView method. You have inflated your R.layout.main in View object called "layout". You have set your actions within that layout. Finally you have returned a new instance of that view. So, your previous codes became useless. So, your return statement will be...
return layout ;
It should fix the problem.
I have a ViewPager that displays GPUImageViews. When creating instances for each page, everything seems great. The problem comes when I tried swiping backwards, to load the previous page. Here's my onCreateView code.
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//I store my previous pages in an imageArray variable to prevent application from rendering image over and over again.
temp = imageArray[this.index]; //temp is a GPUImageView; assume initialized
if (temp.getParent() != null) {
((ViewGroup) temp.getParent()).removeView(temp);
}
temp.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
return temp;
}
When I added removeView() the view pager always return black screen. I tried taking off the removeView() but then it always gives me the error "child view has existing parent...remove parent view first."
EDIT:
to be more specific, i added my onCreate(), init() and renderImage() functions. by the way, this is a Fragment and for my PagerAdapter i'm using FragmentPagerAdapter
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().findViewById(R.id.saveBtn).setOnClickListener(this);
this.init();
this.renderImage();
}
private void init() {
temp = new GPUImageView(getActivity());
this.img = new GPUImageView(getActivity()); //the original image
this.img.setImage(imgUri);
}
private void renderImage() {
temp = this.img;
temp.setFilter(Filter.setFilter(getActivity(), this.filterPosition));
temp.requestRender();
imageArray[this.filterPosition] = temp;
}
I tried debugging to see how my app works...It seems like when creating new instances, onCreate() will always be called followed by onCreateView(). Based from the lifecycle of this guide, I thought only onCreateView() will be called repeatedly.