editText validation and correction with TextWatcher - android

I'm very beginner to programming in android. Sorry if my question is obvious.
I have an editText with inputType="numberDecimal". I watch it's changes with TextWatcher, calculating from it's value (Double type), and show it on a TextView. The calculation is OK, except if the editText has the value ".". If the editText has the value ".", the program drops an error (force close).
My question is: how can I set the editText value to "0." with the use of addTextChangedListener if the editText gets the value "."? Have You got for this situacion a best practice? Thanks in advance for Your help.
My code is:
public class ConversionsFragment extends Fragment{
private EditText etDistBase;
private TextView tvMeterResult;
private TextView tvKmResult;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_conversions, container, false);
etDistBase = (EditText) rootView.findViewById(R.id.textEdit_conv_distance);
tvMeterResult = (TextView) rootView.findViewById(R.id.conv_dist_result_meter);
tvKmResult = (TextView) rootView.findViewById(R.id.conv_dist_result_km);
etDistBase.addTextChangedListener(new TextWatcher(){
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after){
}
public void onTextChanged(CharSequence s, int start, int before, int count){
calculateConvDistances();
}
});
return rootView;
}
private void calculateConvDistances() {
String baseText = etDistBase.getText().toString();
Double baseValue = 0.0,
meterResult = 0.0,
kmResult = 0.0;
// if (baseText == ".") {
// etDistBase.setText("0.");
// baseText = "0";
// }
if (baseText.length() == 0)
baseText = "0";
if (baseText != null) {
baseValue = Double.parseDouble(baseText);
meterResult = baseValue * 1000;
kmResult = baseValue;
} else {
meterResult = 0.0;
kmResult = 0.0;
}
tvMeterResult.setText(Double.toString(meterResult));
tvKmResult.setText(Double.toString(kmResult));
}
}

Try with this
if( editText.getText().toString().equals(".") ){
editText.setText("0.");
}
write into the afterTextChanged() method.

The working solution was to change the "." text to "0." in the afterTextChanged() method, as follows:
public class ConversionsFragment extends Fragment{
private EditText etDistBase;
private TextView tvMeterResult;
private TextView tvKmResult;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_conversions, container, false);
etDistBase = (EditText) rootView.findViewById(R.id.textEdit_conv_distance);
tvMeterResult = (TextView) rootView.findViewById(R.id.conv_dist_result_meter);
tvKmResult = (TextView) rootView.findViewById(R.id.conv_dist_result_km);
etDistBase.addTextChangedListener(new TextWatcher(){
public void afterTextChanged(Editable s) {
if (etDistBase.getText().toString().equals("."))
etDistBase.setText("0.");
etDistBase.setSelection(etDistBase.getText().length());
}
public void beforeTextChanged(CharSequence s, int start, int count, int after){
}
public void onTextChanged(CharSequence s, int start, int before, int count){
calculateConvDistances();
}
});
return rootView;
}
private void calculateConvDistances() {
String baseText = etDistBase.getText().toString();
Double baseValue = 0.0,
meterResult = 0.0,
kmResult = 0.0;
if (baseText.equals(".")) {
baseText = "0";
}
if (baseText.length() == 0)
baseText = "0";
if (baseText != null) {
baseValue = Double.parseDouble(baseText);
meterResult = baseValue * 1000;
kmResult = baseValue;
} else {
meterResult = 0.0;
kmResult = 0.0;
}
tvMeterResult.setText(Double.toString(meterResult));
tvKmResult.setText(Double.toString(kmResult));
}
}

Related

How to stay focus in editText from previous activity when a Dialog Shows?

I'm making a search function through editText that listens a key from a TextWatcher. Now what I'm trying to do is that when the user types the key # it will shows a dialog and runs the recyclerview to show the data within the dialog. The problem is I cannot continue typing from the previous activity because it is in the back stack already and the front one is the DialogFragment that I created.
How would I still continue my focus on the previous activity in the editText even if the dialog fragment shows?
sample code from activity that triggers the dialog
edit_text_chatbox.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
int lastString = s.length();
Character character = s.charAt(lastString - 1);
Log.i("after", "afterTextChanged: "+character);
if (character.toString().equals("#")){
AltTaggingDialogFragment dialog = AltTaggingDialogFragment.newInstance();
dialog.show(getFragmentManager(), "dialog");
}
}
My DialogFragment (AltTaggingDialogFragment)
public class AltTaggingDialogFragment extends DialogFragment{
RecyclerView mRecyclerView;
RecyclerView.Adapter mAdapter_message;
RecyclerView.LayoutManager mLayoutManager;
List<UserFriendList> mUserFriendList;
View view;
EditText friend_tagging;
int friend_count = 7;
#Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
Window window = dialog.getWindow();
int width = ViewGroup.LayoutParams.MATCH_PARENT;
int height = ViewGroup.LayoutParams.WRAP_CONTENT;
WindowManager.LayoutParams windowParams = window.getAttributes();
windowParams.dimAmount = 0.0f;
dialog.getWindow().setLayout(width,height);
windowParams.gravity = Gravity.BOTTOM;
//windowParams.x = width;
windowParams.y = 90;
if (friend_count >= 7)
windowParams.height = (210 * 4) + 150;
dialog.getWindow().setAttributes(windowParams);
dialog.getWindow().setSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
public static AltTaggingDialogFragment newInstance() {
AltTaggingDialogFragment f = new AltTaggingDialogFragment();
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//inflate layout with recycler view
view = inflater.inflate(R.layout.fragment_alt_tagging_dialog, container, false);
friend_tagging = view.findViewById(R.id.friend_tagging);
mRecyclerView = view.findViewById(R.id.alt_tagging_recycler_view);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
friend_tagging.requestFocus();
friend_tagging.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
Toast.makeText(getActivity(), "Toast!", Toast.LENGTH_SHORT).show();
}
});
mUserFriendList = new ArrayList<>();
UserFriendList userFriendList = new UserFriendList();
super.onViewCreated(view, savedInstanceState);
for (int i = 0; i < 8; i++) {
userFriendList.setFirst_name("Mar John");
userFriendList.setLast_name("Saycon");
userFriendList.setUsername("MJ");
mUserFriendList.add(userFriendList);
}
mAdapter_message = new AltTaggingAdapter(getActivity(), mUserFriendList);
mRecyclerView.setAdapter(mAdapter_message);
return view;
}
}
This image shows what I'm trying to do.
Sample Image

Two way binding on custom view

I have a componed view in android contains several textViews and one EditText. I defined an attribute for my custom view called text and getText, setText methods. Now I want to add a 2-way data binding for my custom view in a way its bind to inner edit text so if my data gets updated edit text should be updated as well (that's works now) and when my edit text gets updated my data should be updated as well.
My binding class looks like this
#InverseBindingMethods({
#InverseBindingMethod(type = ErrorInputLayout.class, attribute = "text"),
})
public class ErrorInputBinding {
#BindingAdapter(value = "text")
public static void setListener(ErrorInputLayout errorInputLayout, final InverseBindingListener textAttrChanged) {
if (textAttrChanged != null) {
errorInputLayout.getInputET().addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
textAttrChanged.onChange();
}
});
}
}
}
I tried to bind text with the code below. userInfo is an observable class.
<ir.avalinejad.pasargadinsurance.component.ErrorInputLayout
android:id="#+id/one_first_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="#string/first_name"
app:text="#={vm.userInfo.firstName}"
/>
When I run the project I get this error
Error:(20, 13) Could not find event 'textAttrChanged' on View type 'ir.avalinejad.pasargadinsurance.component.ErrorInputLayout'
And my custom view looks like this
public class ErrorInputLayout extends LinearLayoutCompat implements TextWatcher {
protected EditText inputET;
protected TextView errorTV;
protected TextView titleTV;
protected TextView descriptionTV;
private int defaultGravity;
private String title;
private String description;
private String hint;
private int inputType = -1;
private int lines;
private String text;
private Subject<Boolean> isValidObservable = PublishSubject.create();
private Map<Validation, String> validationMap;
public ErrorInputLayout(Context context) {
super(context);
init();
}
public ErrorInputLayout(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
readAttrs(attrs);
init();
}
public ErrorInputLayout(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
readAttrs(attrs);
init();
}
private void readAttrs(AttributeSet attrs){
TypedArray a = getContext().getTheme().obtainStyledAttributes(
attrs,
R.styleable.ErrorInputLayout,
0, 0);
try {
title = a.getString(R.styleable.ErrorInputLayout_title);
description = a.getString(R.styleable.ErrorInputLayout_description);
hint = a.getString(R.styleable.ErrorInputLayout_hint);
inputType = a.getInt(R.styleable.ErrorInputLayout_android_inputType, -1);
lines = a.getInt(R.styleable.ErrorInputLayout_android_lines, 1);
text = a.getString(R.styleable.ErrorInputLayout_text);
} finally {
a.recycle();
}
}
private void init(){
validationMap = new HashMap<>();
setOrientation(VERTICAL);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
titleTV = (TextView) LayoutInflater.from(getContext()).inflate(R.layout.error_layout_default_title_textview, null, false);
addView(titleTV);
descriptionTV = (TextView) LayoutInflater.from(getContext()).inflate(R.layout.error_layout_default_description_textview, null, false);
addView(descriptionTV);
readInputFromLayout();
if(inputET == null) {
inputET = (EditText) LayoutInflater.from(getContext()).inflate(R.layout.error_layout_defult_edittext, this, false);
addView(inputET);
}
errorTV = (TextView) LayoutInflater.from(getContext()).inflate(R.layout.error_layout_default_error_textview, null, false);
addView(errorTV);
inputET.addTextChangedListener(this);
defaultGravity = inputET.getGravity();
//set values
titleTV.setText(title);
if(description != null && !description.trim().isEmpty()){
descriptionTV.setVisibility(VISIBLE);
descriptionTV.setText(description);
}
if(inputType != -1)
inputET.setInputType(inputType);
if(hint != null)
inputET.setHint(hint);
else
inputET.setHint(title);
inputET.setLines(lines);
inputET.setText(text);
}
private void readInputFromLayout() {
if(getChildCount() > 3){
throw new IllegalStateException("Only one or zero view is allow in layout");
}
if(getChildCount() == 3){
View view = getChildAt(2);
if(view instanceof EditText)
inputET = (EditText) view;
else
throw new IllegalStateException("only EditText is allow as child view");
}
}
public void setText(String text){
inputET.setText(text);
}
public String getText() {
return text;
}
public void addValidation(#NonNull Validation validation, #StringRes int errorResourceId){
addValidation(validation, getContext().getString(errorResourceId));
}
public void addValidation(#NonNull Validation validation, #NonNull String error){
if(!validationMap.containsKey(validation))
validationMap.put(validation, error);
}
public void remoteValidation(#NonNull Validation validation){
if(validationMap.containsKey(validation))
validationMap.remove(validation);
}
public EditText getInputET() {
return inputET;
}
public TextView getErrorTV() {
return errorTV;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
checkValidity();
if(editable.toString().length() == 0) //if hint
inputET.setGravity(Gravity.RIGHT);
else
inputET.setGravity(defaultGravity);
}
public Subject<Boolean> getIsValidObservable() {
return isValidObservable;
}
private void checkValidity(){
//this function only shows the first matched error.
errorTV.setVisibility(INVISIBLE);
for(Validation validation: validationMap.keySet()){
if(!validation.isValid(inputET.getText().toString())) {
errorTV.setText(validationMap.get(validation));
errorTV.setVisibility(VISIBLE);
isValidObservable.onNext(false);
return;
}
}
isValidObservable.onNext(true);
}
}
After hours of debugging, I found the solution. I changed my Binding class like this.
#InverseBindingMethods({
#InverseBindingMethod(type = ErrorInputLayout.class, attribute = "text"),
})
public class ErrorInputBinding {
#BindingAdapter(value = "textAttrChanged")
public static void setListener(ErrorInputLayout errorInputLayout, final InverseBindingListener textAttrChanged) {
if (textAttrChanged != null) {
errorInputLayout.getInputET().addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
textAttrChanged.onChange();
}
});
}
}
#BindingAdapter("text")
public static void setText(ErrorInputLayout view, String value) {
if(value != null && !value.equals(view.getText()))
view.setText(value);
}
#InverseBindingAdapter(attribute = "text")
public static String getText(ErrorInputLayout errorInputLayout) {
return errorInputLayout.getText();
}
First, I added AttrChanged after the text like this #BindingAdapter(value = "textAttrChanged") which is the default name for the listener and then I added getter and setter methods here as well.
event = "android:textAttrChanged" works for me:
object DataBindingUtil {
#BindingAdapter("emptyIfZeroText") //replace "android:text" on EditText
#JvmStatic
fun setText(editText: EditText, text: String?) {
if (text == "0" || text == "0.0") editText.setText("") else editText.setText(text)
}
#InverseBindingAdapter(attribute = "emptyIfZeroText", event = "android:textAttrChanged")
#JvmStatic
fun getText(editText: EditText): String {
return editText.text.toString()
}
}
you need add one more function
#BindingAdapter("app:textAttrChanged")
fun ErrorInputLayout.bindTextAttrChanged(listener: InverseBindingListener) {
}

libPhoneNumber not giving correct US results on edittext

I am trying to create an edit text with a text watcher that displays the phone number correctly, to start out I am just testing it with a US number.
If I go to this site
http://libphonenumber.appspot.com/
And type in US and the number 9188143287 the results look perfect however when I implement the library as they say I am getting different results
Here is my fragment
ublic class PhoneNumberFragment extends Fragment{
private TextView next;
private EditText phoneNumber;
private PhoneNumberUtil phoneUtil;
private AsYouTypeFormatter formatter;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_phone_number, container, false);
phoneUtil = PhoneNumberUtil.getInstance();
formatter = phoneUtil.getAsYouTypeFormatter("US");
init(v);
return v;
}
private void init(View v){
next = (TextView) v.findViewById(R.id.next);
phoneNumber = (EditText) v.findViewById(R.id.phoneNumber);
phoneNumber.addTextChangedListener(new PhoneNumberTextWatcher());
}
private void turnOnNext(){
next.setBackgroundResource(R.color.warningRed);
}
private class PhoneNumberTextWatcher implements TextWatcher{
private boolean isFormatting = false;
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO: implement your code
}
#Override
public void afterTextChanged(Editable s) {
// TODO: implement your code
}
#Override
public synchronized void onTextChanged(CharSequence s, int start, int before,
int count) {
if(before > count) {
return;
}
if(!isFormatting) {
isFormatting = true;
try {
formatter.clear();
for(int i=0; i<s.length();i++) {
phoneNumber.setText(formatter.inputDigit(s.charAt(i)));
phoneNumber.setSelection(phoneNumber.getText().length());
}
} catch (Exception e) {}
isFormatting = false;
}
}
}
}
My results are correct up to 7 digits, but then on the 8th digit the brackets are supposed to appear around the first 3 and they do not.
Thanks for any help!

Use of different TextWatcher-implementations inside RecyclerView.Adapter

Currently I use a RecyclerView to represent a dynamically configuration list form.
Every configuration item (entry at RecyclerView list) contains one EditText item.
To avoid wrong user input (some fields allow only integer, others only one digit after comma), I've implemented two different TextWatcher-filters which correct illegal input ("DecimalFilterDigitsAfterComma" and "DecimalFilterInteger").
My RecyclerView has 16 configuration items in total, but can only display maximum 8 at one time.
My problem is that the TextWatchers are assigned to specific Items (Integers and Decimal-Point TextEdit). But when I'm scrolling a bit, they change their order, so that Decimal- and Integer-Filters get swapped.
The TextWatcher items will be created inside the ConfigurationAdapter which is a RecyclerView.Adapter. I've event managed that the TextWatcher is only created once for each entry by using the mListConfigInit which is a boolean flag list for the items.
ConfigurationAdapter.java:
public class ConfigurationAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
/*
...
*/
private List<ConfigItem> mConfiguration = new ArrayList<>();
// make sure that DecimalFilter is only created once for each item
private List<Boolean> mListConfigInit = new ArrayList<>();
public ConfigurationAdapter() {
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.listitem_configuration,
parent,
false);
final ConfigurationViewHolder vh = new ConfigurationViewHolder(v);
/*
...
*/
return vh;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final ConfigurationViewHolder vh = (ConfigurationViewHolder) holder;
ConfigItem config = mConfiguration.get(position);
if(config.ShowValueAsFloat()) {
vh.SetTextWatcherType(ConfigurationViewHolder.TextWatcherType.type_FloatActive);
} else {
vh.SetTextWatcherType(ConfigurationViewHolder.TextWatcherType.type_IntActive);
}
// set name and unit
vh.mName.setText(config.mName);
vh.mUnit.setText(config.mUnit);
/*
...
*/
}
#Override
public int getItemCount() {
return mConfiguration.size();
}
public void addConfigItem(ConfigItem item) {
mConfiguration.add(item);
mListConfigInit.add(new Boolean(false));
notifyItemInserted(mConfiguration.size() - 1);
//notifyDataSetChanged();
}
/*
...
*/
}
ConfigurationViewHolder.java (changed according to pskink-comments):
public final class ConfigurationViewHolder extends RecyclerView.ViewHolder implements TextWatcher {
public TextView mName;
public CheckBox mCheckbox;
public SeekBar mSeekbar;
public EditText mValueEditText;
public TextView mUnit;
private List<TextWatcher> mListTextWatchers = new ArrayList<>();
public enum TextWatcherType {
type_FloatActive(0),
type_IntActive(1);
private int mValue;
TextWatcherType(int value) {
mValue = value;
}
int val() { return mValue; }
}
private TextWatcherType mTextWatcherType = TextWatcherType.type_FloatActive;
public ConfigurationViewHolder(View itemView) {
super(itemView);
mName = (TextView) itemView.findViewById(R.id.textView_configuration_name);
mValueEditText = (EditText) itemView.findViewById(R.id.editText_configuration_value);
mUnit = (TextView) itemView.findViewById(R.id.textView_configuration_unit);
mCheckbox = (CheckBox) itemView.findViewById(R.id.checkbox_configuration);
mSeekbar = (SeekBar) itemView.findViewById(R.id.seekBar_configuration);
mListTextWatchers.add(0, new DecimalFilterDigitsAfterComma(mValueEditText, 1));
mListTextWatchers.add(1, new DecimalFilterInteger(mValueEditText));
mValueEditText.addTextChangedListener(this);
}
public void SetTextWatcherType(TextWatcherType textWatcherType) {
mTextWatcherType = textWatcherType;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
#Override
public void afterTextChanged(Editable editable) {
mListTextWatchers.get(mTextWatcherType.val()).afterTextChanged(editable);
}
}
DecimalFilterInteger.java
public class DecimalFilterInteger implements TextWatcher {
private final static String TAG = ConfigurationAdapter.class.getSimpleName();
private final EditText mEditText;
private String mLastTextValue = new String("");
public DecimalFilterInteger(EditText editText) {
this.mEditText = editText;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public synchronized void afterTextChanged(final Editable text) {
String strInput = text.toString().trim();
if(strInput.isEmpty()) {
return;
}
if(strInput.equals(mLastTextValue)) { // return when same value as last time to avoid endless loop
return;
}
if ((strInput.charAt(0) == '.')) { // handle dot at beginning
strInput = "";
}
if(strInput.contains(".")){ // cut trailing comma
String numberBeforeDecimal = strInput.split("\\.")[0];
strInput = numberBeforeDecimal;
}
mEditText.removeTextChangedListener(this);
mEditText.getText().clear(); // do not use setText here to avoid changing the keyboard
mEditText.append(strInput); // back to default (e. g. from 123-mode to abc-mode),
// see: http://stackoverflow.com/questions/26365808/edittext-settext-changes-the-keyboard-type-to-default-from-123-to-abc
mLastTextValue = mEditText.getText().toString();
mEditText.setSelection(mEditText.getText().toString().trim().length());
mEditText.addTextChangedListener(this);
}
}
Many thanks in advance for your help!
The cause of the swap/switching behaviour of the two different TextWatcher-implementations inside the RecyclerView was that I called removeTextChangedListenerand addTextChangedListenerinside their afterTextChanged-methods to avoid retriggering of the afterTextChanged-method.
The best way to avoid retriggering is a simple check if the text changed since the last call:
public class DecimalFilterInteger implements TextWatcher {
private final static String TAG = ConfigurationAdapter.class.getSimpleName();
private final EditText mEditText;
private String mLastTextValue = new String("");
// ...
#Override
public synchronized void afterTextChanged(final Editable text) {
String strInput = text.toString().trim();
if(strInput.isEmpty()) {
return;
}
if(strInput.equals(mLastTextValue)) { // return when same value as last time to avoid endless loop
return;
}
if ((strInput.charAt(0) == '.')) { // handle dot at beginning
strInput = "";
}
if(strInput.contains(".")){ // cut trailing comma
String numberBeforeDecimal = strInput.split("\\.")[0];
strInput = numberBeforeDecimal;
}
//mEditText.removeTextChangedListener(this); // CAUSE OF SWAP-ERROR !!!
mEditText.getText().clear(); // do not use setText here to avoid changing the keyboard
mEditText.append(strInput); // back to default (e. g. from 123-mode to abc-mode),
// see: http://stackoverflow.com/questions/26365808/edittext-settext-changes-the-keyboard-type-to-default-from-123-to-abc
mLastTextValue = mEditText.getText().toString();
mEditText.setSelection(mEditText.getText().toString().trim().length());
//mEditText.addTextChangedListener(this); // CAUSE OF SWAP-ERROR !!!
}
}

Android Recycler View not show keyboard in landscape

I have a recyclerview which displays two different types of viewholder, in one type I have an Edit Text field, when the phone is in portrait the keyboard works fine, but when it is in landscape I can't input, when I touch the edit text for input it blinks the keyboard and scrolls to the last position of my list, and at log cat I got "inactive inputConnection" warning. It only happens with phone when I tested it in a tablet it works fine.
Anybody can help me?
View Holder with Edit Text
public static class ViewHolderBack extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
private int qtd;
private Button btnBack;
private Button btnAddCart;
private Button btnSubCart;
private EditText etQuantity;
private TextView tvSubTotal;
private TextView tvTest;
public ViewHolderBack(View itemView) {
super(itemView);
qtd = 1;
btnBack = (Button) itemView.findViewById(R.id.btn_back_front);
btnBack.setOnClickListener(this);
btnAddCart = (Button) itemView.findViewById(R.id.btn_add_cart);
btnAddCart.setOnClickListener(this);
btnAddCart.setOnLongClickListener(this);
btnSubCart = (Button) itemView.findViewById(R.id.btn_sub_cart);
btnSubCart.setOnClickListener(this);
btnSubCart.setOnLongClickListener(this);
etQuantity = (EditText) itemView.findViewById(R.id.tv_quantity);
tvSubTotal = (TextView) itemView.findViewById(R.id.tv_subtotal);
tvTest = (TextView) itemView.findViewById(R.id.tv_card_back);
etQuantity.setText(String.valueOf(qtd));
etQuantity.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (s.length() != 0) {
if (Integer.parseInt(s.toString()) < 2) {
btnSubCart.setEnabled(false);
} else {
btnSubCart.setEnabled(true);
}
}
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
if (s.length() != 0) {
qtd = Integer.parseInt(s.toString());
if (Integer.parseInt(s.toString()) < 2) {
btnSubCart.setEnabled(false);
} else {
btnSubCart.setEnabled(true);
}
} else {
qtd = 0;
etQuantity.setText("0");
}
tvSubTotal.setText(String.format("Total: R$ %.2f", dataset.get(getPosition()).getPrice() * qtd));
}
});
if (qtd == 1) {
btnSubCart.setEnabled(false);
}
}
public TextView getTvTest() {
return this.tvTest;
}
public int getQtd() {
return this.qtd;
}
public TextView getTvSubTotal() {
return tvSubTotal;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_back_front:
IntesigMobileApplication.SELECTED.delete(getPosition());
OrderProductCustomAdapter.adapter.notifyItemChanged(getPosition());
break;
case R.id.btn_add_cart:
qtd = Integer.parseInt(etQuantity.getText().toString());
qtd++;
if (qtd > 1) {
btnSubCart.setEnabled(true);
}
etQuantity.setText(String.valueOf(qtd));
tvSubTotal.setText(String.format("Total: R$ %.2f", dataset.get(getPosition()).getPrice() * qtd));
hideSoftKeyboard(v);
break;
case R.id.btn_sub_cart:
qtd = Integer.parseInt(etQuantity.getText().toString());
qtd--;
if (qtd == 1) {
btnSubCart.setEnabled(false);
}
etQuantity.setText(String.valueOf(qtd));
tvSubTotal.setText(String.format("Total: R$ %.2f", dataset.get(getPosition()).getPrice() * qtd));
hideSoftKeyboard(v);
break;
}
}
My adapter
`public class OrderFragment extends Fragment {
private static final String TAG = "OrderFragment";
private static final String KEY_LAYOUT_MANAGER = "layoutManager";
private static final String KEY_SPAN_COUNT = "spanCount";
private static int SPAN_COUNT = 3;
protected enum LayoutManagerType {
STAGGERED_GRID_MANAGER, LINEAR_LAYOUT_MANAGER
}
protected LayoutManagerType lmtCurrentLayoutManagerType;
protected RecyclerView recyclerView;
protected OrderProductCustomAdapter orderProductCustomAdapter;
protected RecyclerView.LayoutManager rvlayoutManager;
protected List<DummyContent.DummyProduct> mDataset;
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #return A new instance of fragment OrderFragment.
*/
public static OrderFragment newInstance() {
OrderFragment fragment = new OrderFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
public OrderFragment() {
// Required empty public constructor
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
assert ((AppCompatActivity) getActivity()).getSupportActionBar() != null;
((AppCompatActivity) getActivity()).getSupportActionBar().setTitle(R.string.title_orders);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initDataset();
}
private void initDataset() {
this.mDataset = IntesigMobileApplication.PRODUCTS;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_recyclerview, container, false);
rootView.findViewById(R.id.fab).setVisibility(View.GONE);
rootView.setTag(TAG);
//Initialize recycler view
recyclerView = (RecyclerView) rootView.findViewById(R.id.my_recyclerview);
if (savedInstanceState != null) {
// Restore saved layout manager type.
lmtCurrentLayoutManagerType = (LayoutManagerType) savedInstanceState
.getSerializable(KEY_LAYOUT_MANAGER);
if (lmtCurrentLayoutManagerType == LayoutManagerType.STAGGERED_GRID_MANAGER)
SPAN_COUNT = savedInstanceState.getInt(KEY_SPAN_COUNT);
}
orderProductCustomAdapter = new OrderProductCustomAdapter(mDataset);
recyclerView.swapAdapter(orderProductCustomAdapter, false);
recyclerView.setItemAnimator(new CardFlipAnimator(this.getContext()));
recyclerView.getItemAnimator().setSupportsChangeAnimations(true);
if ((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE) {
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
SPAN_COUNT = 3;
setRecyclerViewLayoutManager(LayoutManagerType.STAGGERED_GRID_MANAGER);
} else {
SPAN_COUNT = 2;
setRecyclerViewLayoutManager(LayoutManagerType.STAGGERED_GRID_MANAGER);
}
} else {
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
SPAN_COUNT = 2;
setRecyclerViewLayoutManager(LayoutManagerType.STAGGERED_GRID_MANAGER);
} else {
setRecyclerViewLayoutManager(LayoutManagerType.LINEAR_LAYOUT_MANAGER);
}
}
return rootView;
}
public void setRecyclerViewLayoutManager(LayoutManagerType layoutManagerType) {
int scrollPosition = 0;
int[] positions = new int[]{-1, -1, -1};
switch (layoutManagerType) {
case STAGGERED_GRID_MANAGER:
rvlayoutManager = new StaggeredGridLayoutManager(SPAN_COUNT, StaggeredGridLayoutManager.VERTICAL);
lmtCurrentLayoutManagerType = LayoutManagerType.STAGGERED_GRID_MANAGER;
break;
case LINEAR_LAYOUT_MANAGER:
default:
rvlayoutManager = new LinearLayoutManager(getActivity());
lmtCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
break;
}
if (recyclerView.getLayoutManager() != null) {
if (((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE) ||
(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)) {
scrollPosition = ((StaggeredGridLayoutManager) recyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPositions(positions)[0];
} else {
scrollPosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
}
}
recyclerView.setLayoutManager(rvlayoutManager);
recyclerView.scrollToPosition(scrollPosition);
}`

Categories

Resources