cant change key icon on softKeyboard - java

i am trying to learn android keyboard api.
Using the softKeyboard example, i am trying to change the key icon, i can change everything, but the icon never change.
i am doing it in the LatinKeyboardView, at the onLongPress method, using this line:
copia.icon = getResources().getDrawable(R.drawable.tecladir);
but the icon doesn't change.
Even after using
this.invalidateAllKeys();
to force redraw of the keys, the icon is still unchanged.
Complete code of onLongPress as following:
#Override
protected boolean onLongPress(Key key) {
key.icon = getResources().getDrawable(R.drawable.tecladir);
//tecladir is one image i have
key.text = "batata";
key.label = "batata";
this.invalidateAllKeys();
//default code of method
if (key.codes[0] == Keyboard.KEYCODE_CANCEL) {
getOnKeyboardActionListener().onKey(KEYCODE_OPTIONS, null);
return true;
} else {
return super.onLongPress(key);
}
}
Am i missing something?

Ok, found the solution.
before assign a new icon, the label must be null, otherwise the icon doesn't change, the correct way is:
key.label = null;
key.icon = getResources().getDrawable(R.drawable.tecladir);

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.

Problem adding new sticker on my canvas - Android

I am developing a drawing application where the user can also insert a text sticker with the text they want. For this, when the user selects the text sticker, an AlertDialog appears, where he types the text. When inserting the first text there are no problems. The problem arises when the user already has a sticker and is going to add a new one. When the sticker is added to the canvas, all other stickers disappear, leaving only the new one. However, if the user double-clicks on the new sticker, or once outside the new sticker and clicks inside, the stickers reappear in their proper locations.
I already did a test, where I generate sticker defaults with the same name outside the alertDialog, with just a press of any button, and the stickers are added correctly without the others disappearing. In other words, my stickers just don't work when I use alertDialog. I've already run and I can't find the error. Can someone help me?
MainActivity:
text.setOnClickListener {
showAlertDialogSticker()
}
//Change text color dialog box
private fun showAlertDialogSticker() {
val dialogBuilder = AlertDialog.Builder(this#MainActivity)
val layoutView = layoutInflater.inflate(R.layout.dialog_sticker, null)
checkBold = layoutView.findViewById(R.id.radio_bold)
checkItalic = layoutView.findViewById(R.id.radio_italic)
checkSublime = layoutView.findViewById(R.id.radio_sublime)
pickedColorSticker = layoutView.findViewById(R.id.pickedColorSticker)
txtSticker = layoutView.findViewById(R.id.txt_sticker)
sticker = layoutView.findViewById(R.id.sticker)
multiColorPickerSticker = layoutView.findViewById(R.id.multiColorPickerSticker)
multiColorPickerSticker.setInitialColor(0x7F313C93)
multiColorPickerSticker.subscribe { color: Int, _: Boolean, _: Boolean ->
pickedColorSticker.setBackgroundColor(color)
sticker.setTextColor(color)
textColor = color
}
dialogButtonCancel = layoutView.findViewById(R.id.btnCancel)
dialogButtonAdd = layoutView.findViewById(R.id.btnSave)
dialogBuilder.setView(layoutView)
dialogAdd = dialogBuilder.create()
dialogAdd.window?.attributes?.windowAnimations ?: R.style.DialogAnimation
dialogAdd.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialogAdd.show()
dialogButtonCancel.setOnClickListener {
dialogAdd.cancel()
}
dialogButtonAdd.setOnClickListener {
//Add text sticker
validFiel()
if (isValid) {
my_canvas.addTextSticker(textStick, textColor, null)
dialogAdd.dismiss()
}
}
}
Using the code above I have the problem reported. Calling the method as below, it was possible to add several stickers without problems.
text.setOnClickListener {
my_canvas.addTextSticker(textStick, textColor, null)
}

Detecting current color in window

I am doing a beginner project and I have had a little issue with a radio button. This button's job is to change the theme of the window from light to dark and vice versa.
I'm not too sure on how to ask for Java to detect the value for the Color.decode() method. I want it to check if the current color is either "#21252B" or "#FFFFFF"
I expect it to look kind of like:
if(*however you are supposed to do it*.equals("#21252B")) {
frame.getContentPane().setBackground(Color.decode("#FFFFFF"));
darkMode.setBackground(Color.decode("#FFFFFF"));
} else {
frame.getContentPane().setBackground(Color.decode("#21252B"));
darkMode.setBackground(Color.decode("#21252B"));
}
What can I do?
I figured out what I had to do. Thanks to #AndrewThompson for the suggestion. If anyone needs an answer to a similar problem, here it is. Make
private boolean isDark = true //or false if you want from the get go.
Then, whenever you do your button do the following code
public void actionPerformed(ActionEvent arg0) {
if(isDark == true) {
lightTheme();
isDark = false;
} else {
darkTheme();
isDark = true;
}
after this you should be good to go.

Java showInputDialog select custom text

I have rename dialog for rename file
String renameTo = JOptionPane.showInputDialog(gui, "New Name", currentFile.getName());
it works this way, but I have a problem.
the problem is that I set the default value with the extension of the file
but I just want the file name to be selected.
sample : my file name = yusuf.png
I want select only yusuf like;
There is a lot going on inside JOptionPane, it's one of the things that makes it so powerful, it also makes it a little inflexible to.
Two immediate problems are apparent...
You can't gain direct access to the JTextField been used to get input from the user
The JOptionPane wants to control which components have focus when the dialog is first shown.
Setting up the JTextField is actually straight forward...
String text = "yusuf.png";
int endIndex = text.lastIndexOf(".");
JTextField field = new JTextField(text, 20);
if (endIndex > 0) {
field.setSelectionStart(0);
field.setSelectionEnd(endIndex);
} else {
field.selectAll();
}
This will basically select all the text from the start of the String up to the last . or all the text if no . can be found.
The difficult part now is taking back focus control from the JOptionPane
// Make a basic JOptionPane instance
JOptionPane pane = new JOptionPane(field,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION,
null);
// Use it's own dialog creation process, it's simpler this way
JDialog dialog = pane.createDialog("Rename");
// When the window is displayed, we want to "steal"
// focus from what the `JOptionPane` has set
// and apply it to our text field
dialog.addWindowListener(new WindowAdapter() {
#Override
public void windowActivated(WindowEvent e) {
// Set a small "delayed" action
// to occur at some point in the future...
// This way we can circumvent the JOptionPane's
// focus control
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
field.requestFocusInWindow();
}
});
}
});
// Put it on the screen...
dialog.setVisible(true);
dialog.dispose();
// Get the resulting action (what button was activated)
Object value = pane.getValue();
if (value instanceof Integer) {
int result = (int)value;
// OK was actioned, get the new name
if (result == JOptionPane.OK_OPTION) {
String newName = field.getText();
System.out.println("newName = " + newName);
}
}
And, crossing our fingers, we end up with something looking like...
Personally, I'd wrap this up in a nice reusable class/method call which returned the new text or null based on the action of the user, but that's me
Isn't there an easier way?
Of course, I just like showing you the most difficult solution possible ... 😳 (sarcasm) ... it's kind of why I suggested wrapping it up in it's own utility class, so you can re-use it later 😉

How to hide a View programmatically?

In my application, I have 2 LinearLayout's right above each other. Via a menu option, I want to be able to make the bottom one disappear, and have the top one drop down over the disappeared LinearLayout.
The problem is, I have no idea on how to do this in Java.
It doesn't have to be animated, I want to hide the Layout on return of another activity (the menu), in OnActivityResult. The menu activity sets a boolean on which I check in OnActivityResult, and according to it's value I determine if I need to hide or show the bottom Layout:
// Only change value if it is different from what it was.
if(mUseVolumeButtonAsPTT != resultData.getBoolean("UseVolumeButtonAsPTT")){
mUseVolumeButtonAsPTT = resultData.getBoolean("UseVolumeButtonAsPTT");
if(!mUseVolumeButtonAsPTT){
// Hide lower LinearLayout.
} else {
// Show lower LinearLayout.
}
}
Can anybody give me a hint or a link on how I should do this?
You can call view.setVisibility(View.GONE) if you want to remove it from the layout.
Or view.setVisibility(View.INVISIBLE) if you just want to hide it.
From Android Docs:
INVISIBLE
This view is invisible, but it still takes up space for layout purposes. Use with setVisibility(int) and android:visibility.
GONE
This view is invisible, and it doesn't take any space for layout purposes. Use with setVisibility(int) and android:visibility.
Try this:
linearLayout.setVisibility(View.GONE);
Kotlin Solution
view.isVisible = true
view.isInvisible = true
view.isGone = true
// For these to work, you need to use androidx and import:
import androidx.core.view.isVisible // or isInvisible/isGone
Kotlin Extension Solution
If you'd like them to be more consistent length, work for nullable views, and lower the chance of writing the wrong boolean, try using these custom extensions:
// Example
view.hide()
fun View?.show() {
if (this == null) return
if (!isVisible) isVisible = true
}
fun View?.hide() {
if (this == null) return
if (!isInvisible) isInvisible = true
}
fun View?.gone() {
if (this == null) return
if (!isGone) isGone = true
}
To make conditional visibility simple, also add these:
fun View?.show(visible: Boolean) {
if (visible) show() else gone()
}
fun View?.hide(hide: Boolean) {
if (hide) hide() else show()
}
fun View?.gone(gone: Boolean = true) {
if (gone) gone() else show()
}

Categories

Resources