Android - Loading a different Layout depending on value selected from a Spinner - java

I have a spinner on my home page and when I select a value from the spinner and hit submit my next page loads up with several text boxes.
However, how can I get it so that differnt layouts are displayed according to the value selected from the spinner. I am trying to currently use if statements, however this only works for the first selection, any other causes the app to error out (The application has stopped unexpectedly ... Force close:
String RefType = getIntent().getStringExtra("REFTYPE");
if (RefType.equals("spinner_value_1"))
{
setContentView(R.layout.layoutvalue1);
}
else if (RefType.equals("spinner_value_2"))
{
setContentView(R.layout.layoutvalue2);
}
Any help would be much appeciated.
Thanks

I imagine the error would be because you'd be trying to set the contentView twice, so you could try this:Add int layoutToLoad = 0;*(change here) to the top of your class, this will help us determine what to load. Then in your onCreate:
if (layoutToLoad == 0)
{
setContentView(R.layout.choiceLayout); //whatever the layout with the spinner is
//alternatively you can make the spinner via code
}
else if (layoutToLoad == 1))
{
setContentView(R.layout.layout1);
}
else if (layoutToLoad == 2))
{
setContentView(R.layout.layout2);
}
//etc
then where you're handling your onOptionSelected:
String RefType = getIntent().getStringExtra("REFTYPE");
if (RefType.equals("spinner_value_1"))
{
layoutToLoad = 1;
onCreate(null);
}
else if (RefType.equals("spinner_value_2"))
{
layoutToLoad = 2;
onCreate(null);
}
//etc

Related

The animation for my programatically created button acts weird in my application

So I am facing a weird bug I cannot explain - I cannot even reproduce it sometimes.
Basic context:
I have an application, which lists objects. Every object has a name and a point value. For every object, the addCustomSpinner function creates a "ticket" (a custom view, kind-of-spinner) and shows them in a scrollview so the user can select the one needed. There are four different 'containers' for four different kind of objects - so the layout can be populated with four kind of "ticket" package.
The data for the objects are collected from a database. The addCustomSpinner is called with a for cycle for every object in the database, and - Important - before the for method, the Layout it populates with the tickets is cleared (removeAllViews).
Inside addCustomSpinner, everything is created as "new" - like the button in question.
addCustomSpinner creates this button and adds a new onClickListener. Inside onClickListener, a new boolean is created - this is used to show a different animation when the button is clicked again. On first click (boolean = true), the arrow turns 180 degrees and faces upwards, on second click (boolean = false) the arrow turns 180 degrees and faces downwards. Works like a charm, until...
The bug I am facing:
Sometimes - as I already mentioned, not every time - if I click the button for one "ticket", then leave it 'opened' and click on an another one, and leave it 'opened' also, THEN I choose to populate the layout with a different kind of "ticket" package - The arrow faces upwards by default on every ticket in every package! Sometimes - again, just sometimes - with the same pattern I can turn it back, but it happens just "by accident".
I don't understand how the animation and state of the buttons can be connected, if every created ticket is new, every button is new, every onClickListener is new, and every boolean inside onClickListener is new. And if these are connected somehow, then why can that be that every behavior is "unique" for the buttons, nothing else shows any connection - even this is just a "sometimes" bug, a pretty rare one.
Can anybody help me why this happens?
What I tried:
Well, tried to trace the issue - but since it happens just by accident, I have no clue, I just searched if I can do anything else than the boolean to add different animation for the clicks. Sadly using ObjectAnimator is not a good solution for me - not the same result at least, since my animated arrow not only rotates, but it also changes its color. Shapeshifter seemed like a good idea to create animations easily, but now as I see it, maybe a simple rotation will be my ultimate solution.
Here's the code for the button:
customButton.setOnClickListener(new View.OnClickListener() {
boolean isCustomButtonClicked = true;
#Override
public void onClick(View v) {
if (isCustomButtonClicked) {
customButton.setImageResource(R.drawable.avd_anim_arrow_blue_back);
Drawable d = customButton.getDrawable();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (d instanceof AnimatedVectorDrawable) {
animArrowAnim = (AnimatedVectorDrawable) d;
animArrowAnim.start();
}
}
routeWhoClimbed.setVisibility(View.VISIBLE);
isCustomButtonClicked = false;
} else if (!isCustomButtonClicked) {
customButton.setImageResource(R.drawable.avd_anim_arrow_blue);
Drawable d = customButton.getDrawable();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (d instanceof AnimatedVectorDrawable) {
animArrowAnim = (AnimatedVectorDrawable) d;
animArrowAnim.start();
}
}
routeWhoClimbed.setVisibility(GONE);
isCustomButtonClicked = true;
}
}
});
EDIT:
The full addCustomSpinner():
private void addCustomSpinner(Routes mRouteItemToAdd, String placeName) {
//creating a new View for my custom layout created in xml
View customRoutesView = new View(this);
LinearLayout.LayoutParams customViewParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
customRoutesView.setLayoutParams(customViewParams);
customRoutesView = LayoutInflater.from(this).inflate(
R.layout.custom_view_layout, routeLayout, false
);
//Setting up the views inside the custom view
ImageView imageViewDiffImage = customRoutesView.findViewById(R.id.routeDiffImageView);
TextView textViewRouteName = customRoutesView.findViewById(R.id.routeNameTextView);
TextView textViewRouteDiff = customRoutesView.findViewById(R.id.routeDiffTextView);
ImageButton customButton = customRoutesView.findViewById(R.id.customButton);
RadioButton climberNameOne = customRoutesView.findViewById(R.id.climberNameOne);
RadioButton climberNameTwo = customRoutesView.findViewById(R.id.climberNameTwo);
Button climbedItButton = customRoutesView.findViewById(R.id.climbed_it_button);
RadioGroup climberNameRadioGroup = customRoutesView.findViewById(R.id.climberNameRadioGroup);
RadioGroup climbingStyleRadioGroup = customRoutesView.findViewById(R.id.styleNameRadioGroup);
RelativeLayout routeWhoClimbed = customRoutesView.findViewById(R.id.routeWhoClimbedRelativeLayout);
imageViewDiffImage.setImageResource(R.mipmap.muscle);
textViewRouteName.setText(mRouteItemToAdd.name);
textViewRouteDiff.setText("Difficulty: " + (int) mRouteItemToAdd.difficulty);
climberNameOne.setText(climberName1);
climberNameTwo.setText(climberName2);
routeWhoClimbed.setVisibility(GONE);
//Here comes the button with the animated image
customButton.setOnClickListener(new View.OnClickListener() {
boolean isCustomButtonClicked = true;
#Override
public void onClick(View v) {
if (isCustomButtonClicked) {
customButton.setImageResource(R.drawable.avd_anim_arrow_blue_back);
Drawable d = customButton.getDrawable();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (d instanceof AnimatedVectorDrawable) {
animArrowAnim = (AnimatedVectorDrawable) d;
animArrowAnim.start();
}
}
routeWhoClimbed.setVisibility(View.VISIBLE);
isCustomButtonClicked = false;
} else if (!isCustomButtonClicked) {
customButton.setImageResource(R.drawable.avd_anim_arrow_blue);
Drawable d = customButton.getDrawable();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (d instanceof AnimatedVectorDrawable) {
animArrowAnim = (AnimatedVectorDrawable) d;
animArrowAnim.start();
}
}
routeWhoClimbed.setVisibility(GONE);
isCustomButtonClicked = true;
}
}
});
//Button, works like an 'OK' or something, and I have no
//problem with this
climbedItButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int checkedNameButton = climberNameRadioGroup.getCheckedRadioButtonId();
int checkedStyleButton = climbingStyleRadioGroup.getCheckedRadioButtonId();
RadioButton checkedNameRadioButton = (RadioButton) findViewById(checkedNameButton);
RadioButton checkedStyleRadioButton = (RadioButton) findViewById(checkedStyleButton);
String checkedName = (String) checkedNameRadioButton.getText();
String checkedStyle = (String) checkedStyleRadioButton.getText();
addClimbToDatabase(user.getUid(), checkedName, mRouteItemToAdd, placeName, checkedStyle);
}
});
//And finally, I add this new "ticket" with the custom view to the layout i want to show it. Again, this also works like a charm, no problem here.
routeLayout.addView(customRoutesView);
}
Ultimately, I did not manage to understand the problem throughly, but I was able to eliminate it.
So during my fixing tries I narrowed down the problem to the animated drawable state - credit to #avalerio for his pro tip, but the answer wasn't addig an id to the button. I think somehow and sometime, the state of the first animation (turning the arrow 180 degrees) stuck in the end position - causing the other views using this animatedDrawable showing it in end position on start.
.reset() did not help, since it resets the animatedVectorDrawable object, not the animation xml drawable state. My solution is a kind of workaround, but it is working: when the custom-view 'ticket' is created with the animated-drawable-imagebutton, I set the imageResource of the button to a not-animated xml drawable - this drawable is basically the start position of my animated-drawable. This way, when the 'tickets' are generated, the imagebutton is 'hardcoded' in the start position.
Not elegant, but works. BUT(!) I would really appreciate if someone could explain to me how this weird behavior is possible - just sometimes, randomly, with no pattern I can reproduce intentionally.

How to wait on a button for user input in order to set a variable

I am writing a class that has certain variables that don't need to be set except in certain fringe cases. As such, I am working on writing a requestVariable() method that asks for user input to set that variable when it is needed. However, I am struggling to figure out how to wait for that input before moving on. Let me show you what I have.
SkillApplication AR_D_Atk_Def_1_app = (Unit) -> {
if (Unit.getAttackStatus() != com.codecademy.myapplication.Unit.AttackStatus.DEFENDER) {
return;
}
else {
// Make sure structuresAR is set
Unit.setStructuresAR(requestVariable( /* some parameters */ );
int X;
if (Unit.getStructuresAR() >= 5) {
X = 4;
}
else if (Unit.getStructuresAR() == 4) {
X = 3;
}
else if (Unit.getStructuresAR() == 3) {
X = 2;
}
else {
X = 1;
}
Unit.addCombatAtk(X);
Unit.addCombatDef(X);
}
};
This is a lambda function for a certain skill's application. If this skill needs to be applied, it will run this lambda function. This is one of the fringe cases where the member "structuresAR" of Unit needs to be used. It's very rarely used, and rather than having the user set it every time, I have it set in this lambda function.
VariableRequest<Integer> requestInteger = (VariableRequest<Integer>) (questionMessage, choices, layout) -> {
final Integer[] retVal = new Integer[1];
TextView questionView = new TextView(layout.getContext());
questionView.setText(questionMessage);
EditText textEntry = new EditText(layout.getContext());
textEntry.setInputType(InputType.TYPE_CLASS_NUMBER);
Button submitButton = new Button(layout.getContext());
submitButton.setText("Submit");
layout.addView(questionView);
layout.addView(textEntry);
layout.addView(submitButton);
submitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
retVal[0] = Integer.parseInt(String.valueOf(textEntry.getText()));
}
});
};
Here's what I have written so far for that function. It sets a question, options, and submit button to a layout that updates a return value with what is in the entry box when a button is clicked.
This problem is, this just keeps going. The rest of whatever I've written will be run while the onClickListener is still there, and I don't know how to wait until that's been clicked. I'm coming from C++ knowledge where just writing cin >> variable would pause and wait for you to enter. I'm trying to replicate that with a button.
There's also other problems I can spot with this such as getting the layout from inside a static method, but I struggle to come up with another method as I'm very new to Android development.

Check if ImageView has ColorFilter applied or not?

So I am trying to do Likes in my social app and whether to determine if the like was already applied or not I am trying to see over the color filter
So if the post is not liked it will be white otherwise I will execute this line while pressing on it
buttonlikesHeart.setColorFilter(Color.rgb( 255,0,0 ));
and this works fine but when I want to check if it already has this particular Colorfilter:
if(buttonlikesHeart.getColorFilter() == Color.rgb( 255,0,0 )){
}
it tells me == cannot be applied to Colorfilter and int ?
and if I do
if(buttonlikesHeart.getColorFilter( Color.rgb( 255,0,0 ))){
}
it tells me getColorFilter in ImageView cannot be applied to int
solutions ?
First, make sure you are applying this in an ImageView Not a Button.
"buttonlikesHeart" it should be an ImageView
if(imageView.getColorFilter() == null)
{
Log.i("The Image has no Filter", "No filter");
//Your rest of code here.
}
else
{
Log.i("The Image is Filtered", "Filtered");
//Your rest of code here.
}

How can I get JavaFx Combobox to respond to user typing?

I'm writing a program which involves having a user type in a combo box and the list of items should change to reflect the text in the box (similar to autocomplete when you type into Google)
However, my combo box will not update until I press Enter. It doesn't seem to update when regular keys are typed. I have tried adding all kinds of listeners to the combo box but none of them fix the problem.
Here is the code snippet that has been the most successful. It is called from the fxml code: onKeyReleased="#keyReleased". It works properly, but still only executes when Enter is pressed.
public void keyReleased() throws SQLException, ClassNotFoundException
{
String coname = custconame_combo.getValue();
scriptHandler = new ScriptHandler();
custconame_combo.getItems().clear();
int i = 0;
for (String s : scriptHandler.searchCustomer(coname))
{
System.out.println(s);
custconame_combo.getItems().add(s);
custconame_combo.show();
i += 1;
}
}
I have searched high and low and still can't seem to solve this issue.
Since I've solved my problem, I'll share what I found.
Third party libraries provided the easiest solution. I went with the autocompletion class from JFoenix. It has exactly the functionality I was looking for and didn't feel like I was trying to reinvent the wheel.
This answer was very helpful in my search: JavaFX TextField Auto-suggestions
Just had a similiar porblem. The onKeyReleased method doesn't respond as needed. Use the EventHandler.
Here is my code (just tested and works well):
currencySymbolComboBox.setOnKeyPressed(event -> {
if(currencySymbolComboBox.isShowing()) {
if(event.getCode().isLetterKey()) {
currencyComboBoxKeysTyped += event.getCode().getName();
Optional<String> os = currecnySymbolsObservableList.stream()
.filter(symbol -> symbol.startsWith(currencyComboBoxKeysTyped))
.findFirst();
if (os.isPresent()) {
int ind = currecnySymbolsObservableList.indexOf(os.get());
ListView<String> lv = ((ComboBoxListViewSkin) currencySymbolComboBox.getSkin()).getListView();
lv.getFocusModel().focus(ind);
lv.scrollTo(ind);
currencySymbolComboBox.getSelectionModel().select(ind);
} else {
currencyComboBoxKeysTyped = currencyComboBoxKeysTyped
.substring(0, currencyComboBoxKeysTyped.length() - 1);
}
}
else if(event.getCode() == KeyCode.BACK_SPACE) {
if(currencyComboBoxKeysTyped.length() > 0) {
currencyComboBoxKeysTyped = currencyComboBoxKeysTyped
.substring(0, currencyComboBoxKeysTyped.length() - 1);
}
}
}
});
currencySymbolComboBox.showingProperty().addListener((observable, oldValue, newValue) -> {
if(!currencySymbolComboBox.isShowing()) {
currencyComboBoxKeysTyped = "";
}
});

Change multiline EditText cursor position without opening keyboard

I am creating a dialog that has a EditText in it. The dialog takes more than half the screen and the logic of the dialog doesn't allow to use a keyboard.
I was using this solution Android 4.0 EditText without soft keyboard and with cursor positioning but I found out that when you have a multi line EditText, it doesn't work since you can only select the first line.
Is there a solution available for multi-line EditText?
For single-line, this works:
if(v.getId() == R.id.emo_text_field){
Layout layout = ((EditText) v).getLayout();
float x = event.getX() + v.getScrollX();
int offset = layout.getOffsetForHorizontal(0, x);
if(offset>0){
if(x>layout.getLineMax(0)){
((EditText) v).setSelection(offset); // touch was at end of text
}
else{
((EditText) v).setSelection(offset - 1);
}
}
return true;
}
As requested, this is the solution I found for this:
public void disableSoftInputFromAppearing(EditText editText) {
if (Build.VERSION.SDK_INT >= 11) {
editText.setRawInputType(InputType.TYPE_CLASS_TEXT);
editText.setTextIsSelectable(true);
} else {
editText.setRawInputType(InputType.TYPE_NULL);
editText.setFocusable(true);
}
}
And in your onCreate, just put:
disableSoftInputFromAppearing(editTextView);
That way, the keyboard won't appear on any SDK version of Android. Hope it helps someone else.

Categories

Resources