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.
Related
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.
If I click a button 1 time, so it should to show number "1" in a textview. If I click again, so its should to show "2"...
#Override
public void onClick(View p1){
int id = p1.getId();
double x = 0;
//button clicked
if(id == R.id.button_contar){
x++; /*its only shows "1". When I click again, shows "1" again*/
this.mViewHolder.contados.setText(String.format("%.0f", x));
}
}
One possible approach is to initially set 0 in the textview, and with every button click you first fetch the current value in textView and then increment the value and set the new Value
int id = p1.getId();
//button clicked
if(id == R.id.button_contar){
int current = Integer.parseInt(this.mViewHolder.contados.getText().toString());
current++;
this.mViewHolder.contados.setText(String.format("%.0f", current));
}
I don't have any editor right now, so there might be some syntax errors with the above code. It will give you a rough idea on how you should solve your issue
So I have a button, and this button switches the cell of a listview with the cell above, and vise versa for ANOTHER button which is for down (this one is for up... It doesn't matter which, I just decided to talk about this one). The whole button and list view thing is working, but my problem is when I press the up button, and then decide to press it again, it just acts as a down button. The reason for this is because it's still stuck on the same item/position of the list view, and I need to figure out a way to Override the position of the onItemClick in the code??
```
upButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//upButton onClick
Integer myTeam = position; //7 -159
Integer otherTeam = position - 1; //6 - 1678
Map<Integer, String> onClickMap = sortByValue(Constants.picklistMap);
String extraValue;
Log.e("myposition", myTeam.toString());
Log.e("otherposition", otherTeam.toString());
extraValue = onClickMap.get(myTeam); //159
String team = onClickMap.get(otherTeam);
Constants.picklistMap.put(myTeam, onClickMap.get(otherTeam));
Constants.picklistMap.put(otherTeam, extraValue); //6
Log.e("Position: ",Constants.picklistMap.get(position));
Log.e("Position - 1: ",Constants.picklistMap.get(position - 1));
if(myTeam != 0) {
dref.child("picklist").child(myTeam.toString()).setValue(Integer.parseInt(Constants.picklistMap.get(myTeam)));
dref.child("picklist").child(otherTeam.toString()).setValue(Integer.parseInt(Constants.picklistMap.get(otherTeam)));
} else {
Toast.makeText(getActivity(), "Nice try.
If you try it again, the app is going to crash as punishment ... (:",
Toast.LENGTH_LONG).show();
}
}
});
```
By overriding the position, I just mean how
position =+ 1
would make position = position + 1 in python, and I want to do the same thing in Java. The problem is I know that can't be done using the snippet of code I just used to increment the value of position!
Please help!
The reason I can't use position = position + 1 is because on the onItemClick, int position is defined, and then the onClick is created for the buttons, so I need position to be final for me to use it in the onClick, and if I got rid of final, i wouldn't be able to use it in the onClick as it can't be accessed from within an inner class when it's not final
Define which position you want to change, and use this method to update position. You can use this method in onClickListener. This should work.
private int position = 0;
private void up(ArrayList<Integer> arr){
if (position < 1 || position >= arr.size()) return;
int temp = arr.get(position - 1);
arr.set(position - 1, arr.get(position));
arr.set(position, temp);
position --;
}
I have two elements (TextView) in my XML layout that when a LongClick is pressed it will prompt the user to enter in a new value and then when the DONE button is clicked it should show the newly inputed value to the tvScoreHome using setText().
When I do a Long Click on the mentioned element the edit field and keyboard appear as expected. However, it won't allow me to type anything. When I type something it nothing shows up (but the device vibrates as if a button was pressed) and when the DONE button is clicked it vibrates as well but it does not exit the keyboard and show anything in the tvScoreHome element.
Any ideas why?
// set the onLongClickListener for tvScoreHome
tvScoreHome.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
final EditText userInput = (EditText) findViewById(R.id.userInput);
InputMethodManager imm = (InputMethodManager) context.getSystemService(Service.INPUT_METHOD_SERVICE);
userInput.setVisibility(View.VISIBLE);
imm.showSoftInput(userInput, 0);
tvScoreHome.setText( userInput.getText() );
userInput.setVisibility(View.INVISIBLE);
return true;
}
});
You need to give the user a chance to input some text before copying the data and hiding the EditText.
Remove these two lines from your listener:
tvScoreHome.setText( userInput.getText() );
userInput.setVisibility(View.INVISIBLE);
Perhaps you could use an OnFocusChangeListener to run these two lines when userInput loses focus.
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