i am subclassing TextInputEditText so that i can add a string to a password editText field. here is the subclass:
public class CustomInputEditTextWithPrefix extends TextInputEditText {
public CustomInputEditTextWithPrefix(Context context) {
super(context);
}
public CustomInputEditTextWithPrefix(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomInputEditTextWithPrefix(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public Editable getText() {
Editable s = (Editable) super.getText(); //why is this causing infinite stackoverflow ?
if(s!=null && s.length()>0) {
//salt the password
Editable pwSalt = new SpannableStringBuilder("my secret string");
s= pwSalt.append(s);
}
return s;
}
}
and the imlementation in xml is:
<com.myapp.ui.auth.ui.customviews.CustomInputEditTextWithPrefix
android:id="#+id/password"
android:inputType="textPassword" />
my issue is that when i execute the code the getText() override method keeps getting called over and over again. i took out the inputType but its still being called until stackoverflow. my idea was to append to the front of every string in the TextInputEditText a secret hash. What am i doing wrong ?
Maybe if you skip to assign a new value of s everything will be OK
#Override
public Editable getText() {
Editable s = (Editable) super.getText();
if(s!=null && s.length()>0) {
//salt the password
return new SpannableStringBuilder("my secret string").append(s.toString());
}
return s;
}
Related
I want to create a custom Text View and set its text by applying some function to the passed value.
For example if my xml is:-
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="#dimen/margin_raptor_medium"
android:text="someText"/>
then I would want to take the someText; apply my transformation function to it and set the Text again. basically this will be my string Id for which I will fetch the translation from my function.
EDIT:-
so In my custom view class, I am overriding the set Text Method like this:-
#Inject
StringRepository stringRepository
#Override
public void setText(CharSequence text, BufferType type) {
System.out.println("In SetTExt Method");
// modify text here
System.out.println("The text that is set here is:" + text);
String modifiedText = StringRepository.getString((String)text);
super.setText(modifiedText, type);
}
Now the getString Method is giving a Null pointer exception as the map that it accesses is not getting updated.
I am updating this map during Login Time.
Extend TextView class first and then override setText() method, where you can do all the transformations. Thats it.
It should look something like this:
class YouTextView extends TextView {
public YouTextView(Context context) {
super(context);
}
public YouTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public YouTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setText(CharSequence text, BufferType type) {
// modify text here
super.setText(modifiedText, type);
}
}
I have an edittext an it have many words in it. After I paste it some keywords and I want to catch only pasted keywords.
I find different solution but its only gave me text is pasted or cut. I want keywords too.
How to detect the paste event in editext of the application?
Is there any solution like swift or Do we have to hack again.
And sorry for my terrible english.
"Test Test Test" -> paste new -> "Test Test Pasted Text Here Test"
I want to get "Pasted Text Here"
You have to make a custom EditText that can catch paste event. For that, it will need to override onTextContextMenuItem(int id)
Something like that is enough :
public class MyEditText extends EditText {
UpdateListener listener;
public MyEditText(Context context) {
super(context);
}
public MyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MyEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void setUpdateListener(UpdateListener listener){
this.listener = listener;
}
#Override
public boolean onTextContextMenuItem(int id) {
boolean consumed = super.onTextContextMenuItem(id);
switch (id){
case android.R.id.cut :
if(listener != null) listener.onCut();
break;
case android.R.id.copy :
if(listener != null) listener.onCopy();
break;
case android.R.id.paste :
if(listener != null) listener.onPaste();
}
return consumed;
}
interface UpdateListener{
void onCut();
void onCopy();
void onPaste();
}
}
Then, in activity, you have to implement the interface given by this custom EditText
editText = findViewById(R.id.textview2);
editText.setUpdateListener(new MyEditText.UpdateListener() {
#Override
public void onCut() {
Log.i(TAG, "onCut: ");
}
#Override
public void onCopy() {
Log.i(TAG, "onCopy: ");
}
#Override
public void onPaste() {
Log.i(TAG, "onPaste: ");
// triggered when code is pasted
}
});
If i understand well you want that when the user paste somethinig, it erases what was written and paste the text.
In onPaste() :
#Override
public void onPaste() {
Log.i(TAG, "onPaste: ");
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
String pasteData = "";
//check if something present in clipboard, and check if it is text
if (clipboard.hasPrimaryClip() && clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN)) {
ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
pasteData = item.getText().toString();
editText.setText(pasteData);
}
}
take a look at the documentation for autofill here
. Specifically AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE constant. So i have set up auto fill in oreo emulator and it works great for getting the users credit card info that was stored. But the issue is the expiry date is coming from autofill in the format "09/19" but i need it as "09/2019". From the docs it says we can override getAutofillType() to return AUTOFILL_TYPE_DATE.
I dont get it ? because this way it will return epoch time'date to me. How do i get it to return the date in the format i desire ?
Google gave instructions how to do this:
You define a date autofill value for the view by overriding the following methods:
getAutofillType() to return AUTOFILL_TYPE_DATE.
getAutofillValue() to return a date autofillvalue.
autofill(AutofillValue) to expect a data autofillvalue.
given that here is what i have so far in a custom editText:
public class AutoFillDateFormEditText extends AppCompatEditText{
public AutoFillDateFormEditText(Context context) {
super(context);
}
public AutoFillDateFormEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AutoFillDateFormEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public int getAutofillType() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return AUTOFILL_TYPE_DATE;
}
else return super.getAutofillType();
}
#Override
public void autofill(AutofillValue value) {
super.autofill(value); //what goes here ? im lost
}
#Nullable
#Override
public AutofillValue getAutofillValue() {
return //what should i return here ????
}
}
Even if i hold breakpoints on the recommended overrides only getAutofillType() gets a break point hit, the rest of the overrided methods are not hit. i downloaded the google sample app "autofill Sample" and tried it and the date is also not working. so i dont think its me doing something wrong yet. I am testing on a oreo emulator api 26 Nexus 6P.
the same instructions are here: https://developer.android.com/guide/topics/ui/controls/pickers.html#PickerAutofill
but seem to not be currently working(at least on emulator) with system auto fill service.
you need to override autofill in order to set the desired format.
you need to override getAutofillValue in order to let the class convert an input in your edit text to an AutoFill object.
public class AutoFillDateFormEditText extends AppCompatEditText {
public AutoFillDateFormEditText(Context context) {
super(context);
}
public AutoFillDateFormEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AutoFillDateFormEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public int getAutofillType (){
return AUTOFILL_TYPE_DATE;
}
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void autofill(AutofillValue value) {
if (!value.isDate()) {
Timber.w(value + " could not be autofilled into " + this);
return;
}
long autofilledValue = value.getDateValue();
// First autofill it...
setText(dateFormat.format(new Date(autofilledValue)));
// ...then move cursor to the end.
final CharSequence text = getText();
if ((text != null)) {
Selection.setSelection((Spannable) text, text.length());
}
}
#RequiresApi(api = Build.VERSION_CODES.O)
#Nullable
#Override
public AutofillValue getAutofillValue() {
final AutofillValue autofillValue = super.getAutofillValue();
if ( autofillValue == null)
return null;
final Date date = tryParse(autofillValue.getTextValue().toString());
return date != null ? AutofillValue.forDate(date.getTime()) : autofillValue;
}
private final DateFormat dateFormat = new SimpleDateFormat("MM/yyyy");
java.util.Date tryParse(String dateString)
{
try
{
return dateFormat.parse(dateString);
}
catch (ParseException e) {
return null;
}
}
}
You can Format the Date using SimpleDateFormat.
DateFormat originalFormat = new SimpleDateFormat("MM/yy", Locale.ENGLISH);
DateFormat targetFormat = new SimpleDateFormat("MM/yyyy");
Date date = originalFormat.parse("09/19");
I have an array of EditText and I want to disable the standard keyboard Android that appears every time I click on them.
these are the parts code I am using:
InputMethodManager imm = (InputMethodManager)getSystemService(
Context.INPUT_METHOD_SERVICE);
for (i=0;i<dim*dim;i++){
imm.hideSoftInputFromWindow(value[i].getWindowToken(), 0);
value[i].setOnTouchListener(this);
value[i].setOnClickListener(this);
value[i].setOnFocusChangeListener(this);
}
EDIT:
I created a new class, with these lines of code:
import android.content.Context;
import android.util.AttributeSet;
import android.widget.EditText;
public class KeyboardControlEditText extends EditText {
private boolean mShowKeyboard = false;
public void setShowKeyboard(boolean value) {
mShowKeyboard = value;
}
// This constructor has to be overriden
public KeyboardControlEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
// Now tell the VM whether or not we are a text editor
#Override
public boolean onCheckIsTextEditor() {
return mShowKeyboard;
}
}
and in my main class in OnCreate:
for (i=0;i<dim*dim;i++){
((KeyboardControlEditText) value[i]).setShowKeyboard(false);
value[i].setOnTouchListener(this);
value[i].setOnClickListener(this);
}
You need to create your own EditText class for this. Then, override the default onCheckIsTextEditor and return false.
public class NoKeyboardEditText extends EditText {
// This constructor has to be overriden
public NoKeyboardEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
// Now tell the VM that we are not a text editor
#Override
public boolean onCheckIsTextEditor() {
return false;
}
}
Make sure you substitute in the correct name for the new EditText. For example, if your package is com.example.widget, you'd want to use <com.example.widget.NoKeyboardEditText ... />.
If you need this to be dynamic, you can get even fancier:
public class KeyboardControlEditText extends EditText {
private boolean mShowKeyboard = false;
public void setShowKeyboard(boolean value) {
mShowKeyboard = value;
}
// This constructor has to be overriden
public KeyboardControlEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
// Now tell the VM whether or not we are a text editor
#Override
public boolean onCheckIsTextEditor() {
return mShowKeyboard;
}
}
That way, you can call ((KeyboardControlEditText) myEditText).setShowKeyboard(false); to change it at runtime.
Using a simple EditTextPreference in my preferences activity:
<EditTextPreference
android:key="SomeKey"
android:title="#string/some_title"
android:summary="..."
android:numeric="integer"
android:maxLength="2"
/>
Is there a way that this configuration value would be saved as integer? Seems now it just allows to enter numbers, but the value is still saved as string:
Calling:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
int value = preferences.getInt("SomeKey", -1);
throws me java.lang.ClassCastException: java.lang.String, and:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String value = preferences.getString("SomeKey", "-1");
retrieves the value successfully.
How to make PreferenceActivity to save value as integer by default?
You could extend EditTextPreference:
public class IntEditTextPreference extends EditTextPreference {
public IntEditTextPreference(Context context) {
super(context);
}
public IntEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public IntEditTextPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected String getPersistedString(String defaultReturnValue) {
return String.valueOf(getPersistedInt(-1));
}
#Override
protected boolean persistString(String value) {
return persistInt(Integer.valueOf(value));
}
}
It would be better to overwrite onSetInitialValue() and setText() methods, but then you would have to copy some code from a base class. Above solution is simplier, but it's quite tricky - "string" methods do something with ints. Try to not extend this class further ;-)
You could use it from XML by:
<package.name.IntEditTextPreference
android:key="SomeKey"
android:title="#string/some_title"
android:summary="..."
android:numeric="integer"
android:maxLength="2"
/>
Even if you set android:numeric="integer" it'll be text preference - as its name suggest. You could easily convert string value to int using Integer.valueOf(). Also you could overwrite PreferenceActivity to do conversion automatically on exit.
I think the best solution is to write simple method to get this value from preferences. Something like:
public static int getSomePref(Context context) {
SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(context);
String value = prefs.getString("SomeKey", null);
return value == null ? -1 : Integer.valueOf(value);
}
Then you could very easily use it from your code.
Even though an Answer has been parked accepted I would like to share one more shorter way to achieve this :
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
int value = Integer.parseInt(preferences.getString("SomeKey", "-1"));
Since you have already set that only numbers can be entered this won't through any exception.
yet to complete my answer :
<EditTextPref
android:key="SomeKey"
android:title="#string/some_title"
android:summary="..."
android:numeric="integer"
android:maxLength="2" />
I know this is an old question with an already accepted answer but I think my solution can be helpful for someone searching for a more complete answer. I have just improved #broot answer a litte and there goes my solution:
Override the EditTextPreference to provide text to int conversion:
public class IntEditTextPreference extends EditTextPreference implements EditTextPreference.OnBindEditTextListener {
private String mText;
public IntEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setOnBindEditTextListener(this);
}
public IntEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOnBindEditTextListener(this);
}
public IntEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setOnBindEditTextListener(this);
}
public IntEditTextPreference(Context context) {
super(context);
setOnBindEditTextListener(this);
}
/**
* Saves the text to the current data storage.
*
* #param text The text to save
*/
public void setText(String text) {
final boolean wasBlocking = shouldDisableDependents();
mText = text;
int value = Integer.parseInt(text);
persistInt(value);
final boolean isBlocking = shouldDisableDependents();
if (isBlocking != wasBlocking) {
notifyDependencyChange(isBlocking);
}
notifyChanged();
}
/**
* Gets the text from the current data storage.
*
* #return The current preference value
*/
public String getText() {
return mText;
}
#Override
protected void onSetInitialValue(Object defaultValue) {
int value;
if (defaultValue != null) {
String strDefaultValue = (String) defaultValue;
int defaultIntValue = Integer.parseInt(strDefaultValue);
value = getPersistedInt(defaultIntValue);
} else {
value = getPersistedInt(0);
}
setText(Integer.toString(value));
}
#Override
public boolean shouldDisableDependents() {
return TextUtils.isEmpty(mText) || super.shouldDisableDependents();
}
#Override
public void onBindEditText(#NonNull EditText editText) {
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
}
}
In the preferences xml:
<your.package.here.IntEditTextPreference
android:key="some_key"
android:title="#string/some_title"
android:defaultValue="5"
app:useSimpleSummaryProvider="true"/>
Note: Don't use android:numeric nor android:inputType. Since EditTextPreference is not an EditText itself setting those attributes will do nothing. In order to achieve the desired effect on the EditText from the Dialog opened by the EditTextPreference, just set the input type in your custom EditTextPreference by implementing EditTextPreference.OnBindEditTextListener as you can see in the code above.
That's what worked for me.
I had the same Problem. (I wanted SharedPreference to give me a port number that i stored in a preferences xml file as defaultValue).
Implementing all the SharedPreferences methods would be much effort, so writing a custom method in the class that instanced the SharedPreferences, as broot suggested would be best i think.
You can aswell just use the Static method of Integer in the line where you need it:
int number = Integer.valueOf(settings.getString("myNumberString", "0"));
I think this is the shortest one I could come up with:
int CheckInterval = Integer.parseInt(sharedPreferences.getString("check_frequency","60"));