I wonder in case there is a ready implantation for textarea view that expand as user type more text. like the android built in SMS message text area.
I got a partial answer :) - i needed an SMS Style Textfield as well, so I made one myself, including a textwatcher that tracks how many characters are left.
This is what it will look like:
The Textwatcher implementation
public class SMSTextWatcher implements TextWatcher {
private final int maxLength;
private final int stringId;
private final TextView textView;
/**
* #param maxLength maximum number of characters that are allowed
* #param stringId must have at least one %s in it, for the updated character count.
* #param targetView target text view that displays the number of characters left.
*/
public SMSTextWatcher(int maxLength, int stringId, TextView targetView) {
this.maxLength = maxLength;
this.textView = targetView;
this.stringId = stringId;
updateTextView(maxLength);
}
#Override
public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable editable) {
//Update textview (the limit is handled by the maxLength attribute)
updateTextView(maxLength - editable.length());
}
public void updateTextView(int charactersLeft) {
textView.setText(String.format(textView.getContext().getString(stringId), charactersLeft));
}
}
The Layout XML - let's call it widget_sms_field.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="#+id/sms_field_text"
style="#style/TextAppearance.AppCompat.Large"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:hint="#string/short_text"
android:imeOptions="actionSend|flagNoEnterAction"
android:inputType="textShortMessage|textAutoCorrect|textCapSentences|textMultiLine"
android:maxLength="#integer/sms_text_max_length"
android:paddingRight="10dp"
android:singleLine="false" />
<TextView
android:id="#+id/sms_field_remaining_characters"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:text="#string/remaining_characters"
android:textColor="#color/secondary_text" />
</LinearLayout>
The Max Length
In above layout file we used android:maxLength="#integer/sms_text_max_length"
to resolve it, we'll have to create a file called "integer.xml" in the values folder of your project. The content of the file should be as follows:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="sms_text_max_length" type="integer">160</item>
</resources>
If you name the file something other than "integer" - make sure to also change the #integer/sms_text... accordingly.
The "x characters left" Text
The little grey-colored text field(#color/secondary_text - you need to create this color yourself!) with the id sms_field_remaining_characters is the field which will display how many characters are left. For this purpose create a new string resource:
<string name="remaining_characters">%s remaining Characters</string>
Include the widget layout xml in your own layout and in your Fragment's onViewCreated method link the SMSTextWatcher to our sms-style field:
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
EditText textField = (EditText) view.findViewById(R.id.sms_field_text);
textField.addTextChangedListener(new SMSTextWatcher(
getResources().getInteger(R.integer.sms_text_max_length),
R.string.remaining_characters,
(TextView) view.findViewById(R.id.sms_field_remaining_characters)));
}
Done :) ! Let me know, if you have questions or suggestions!
Related
I have an Edittext in my application. I have set it's default color to black in the following manner in the XML:
android:textColor="#android:color/black"
LAYOUT:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
tools:context="scientificcalculatorapp.scientificcalculator.ScientificCalculator"
android:weightSum="1"
android:orientation="vertical"
android:layout_alignParentBottom="true">
<LinearLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#android:color/transparent"
android:focusable="true"
android:focusableInTouchMode="true">
</LinearLayout>
<EditText
android:layout_width="match_parent"
android:layout_height="48dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="#+id/Output"
android:enabled="true"
android:focusable="true"
android:longClickable="true"
android:inputType="text"
android:textIsSelectable="true"
android:cursorVisible="true"
android:textColor="#android:color/black"
android:bufferType="spannable"
android:background="#android:color/darker_gray"
android:allowUndo="true" />
</LinearLayout>
This works when I get input from my keypad but when I copy something in a different color from a different application and then paste it in this EditText, the text gets pasted in this other color and not black.
How can I standardize the color to be black regardless of whatever color I copied it in.
UPDATE:
output.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
String yourCopiedString=output.getText().toString();
int length = yourCopiedString.length();
Spannable spannable= new SpannableString(yourCopiedString);
//set color
//set size
spannable.setSpan(new ForegroundColorSpan(Color.BLACK), 0,length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new RelativeSizeSpan(5.0f), 0,length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
output.setText(spannable);
}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
}
});
The copy-paste behavior varies from vendor to vendor depending upon the functionality they have added.
My suggestion is, set an onFocusChangeListener to your editText, when the EditText loses its focus override the textColor again ! This is a simple work around. Try and let me know.
Update:
As you have only one, EditText field, it never loses the focus and the above solution needs to be little tweaked.
In the layout, add another EditText field. Set it's visibility to GONE. For the existing EditText field, add android:imeOptions="actionNext".
In your activity, to the newly added 'EditTextfield, set it's input type toTYPE_NULL. Now, when the user pressesnextbutton in the keyborad, yourEditText` will loses the focus resulting in changing the textColor. This is work around, not a solution.
ok, here is a try. I don´t know if it solves the problem, but need to show code. First create a style:
<style name="NormalText" parent="#android:style/TextAppearance">
<item name="android:textColor">#android:color/black</item>
<item name="android:textSize">15sp</item>
</style>
then add a TextWatcher to your EditText
output.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) {
}
}
create a global boolean value and ClipboardManager:
private ClipboardManager clipBoard;
private boolean addedToClipboard = false;
initialize and add a listener to the Manager:
clipBoard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
clipBoard.addPrimaryClipChangedListener(new ClipboardManager.OnPrimaryClipChangedListener() {
#Override
public void onPrimaryClipChanged() {
addedToClipboard = true;
}
});
Then do the following in AfterTextChanged:
#Override
public void afterTextChanged(Editable s) {
Log.d("TAPPJABB", "AFTER TEXT CHANGED:" + s);
if (addedToClipboard == true) {
String yourCopiedString = output.getText().toString();
int length = yourCopiedString.length();
Spannable spannable = new SpannableString(yourCopiedString);//set color
spannable.setSpan(new ForegroundColorSpan(Color.BLACK), 0, length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new RelativeSizeSpan(5.0f), 0, length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
addedToClipboard = false;
output.setText(spannable);
}
}
It´s important to follow the order here to avoid infinite loop. The boolean value prevents a normal input from beeing formatted, in this example it works only for clipboard paste.
But like you mentioned, it works not if you want to paste it multiple times, what usually nobody do on one EditText. The problem here is, that we are left alone here from Google, there is no paste-listener or another solution for the editText, at least I couldn´t find anything.
Hi all,
I'm banging my head with a problem that seems intractable to me (perhaps my ignorance x).
I have a TextView in which a string when I write, I calculate the space available and if necessary I reduce the font size to a minimum size set, then add a line and keep writing.
PROBLEM:
Writing strings of buttons 2 and 3, display the lines of the TextView are filled in correctly: the first line is complete and the rest of the string goes on the second line.
ES.:
56688+(555556565555566
555555
56688x(555556565555566
555555
Writing strings of buttons 1 and 4, show the lines of the TextView are filled incorrectly:
the first line is filled up to the '/' or '-' remained largely empty, and the text after the character is on the second line.
ES.:
56688/
(555556565555566555555
56688-
(555556565555566555555
The intended behavior is that of the strings of the buttons 2 and 3.
I can not understand why it behaves abnormally in the presence of the characters '/' and '-', and how to remedy this anomaly.
I enclose code:
In the file "activity_main.xml" I have a custom component that I report below:
<LinearLayout android:id="#+id/mainLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
androidrientation="vertical"
android:layout_alignParentTop="true">
<com.example.component.NumTextView
android:id="#+id/textViewInput"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:gravity="right"
android:maxHeight="64dp"
android:minHeight="64dp"
app:lines="1"
app:maxLines="3"
app:mintextsize="16"
app:maxtextsize="48"
androidadding="0dp"
android:scrollbars="vertical"
android:singleLine="false" android:text="" />
<View android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#000000" />
In the class "NumTextView" that inherits from "TextView" I have the following code:
private void refitText(String text, int textWidth)
{
float trySize = 23;
if( textWidth > 0 )
{
int lineCount = this.getLineCount();
this.setLines(lineCount + 1);
this.setVerticalScrollBarEnabled(true);
this.setMovementMethod(ScrollingMovementMethod.get Instance());
this.setTextSize(trySize);
}
}
#Override
protected void onTextChanged(final CharSequence text, final int start, final int before, final int after)
{
refitText( text.toString(), this.getWidth() );
}
Finally, in "MainActivity" I have the following code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textInput = (NumTextView) findViewById(R.id.textViewInput);
}
public void onClick1(View v)
{
String stringa ="56688-(555556565555566555555";
textInput.setText(stringa);
}
public void onClick2(View v)
{
String stringa ="56688+(555556565555566555555";
textInput.setText(stringa);
}
public void onClick3(View v)
{
String stringa ="56688x(555556565555566555555";
textInput.setText(stringa);
}
public void onClick4(View v)
{
String stringa ="56688/(555556565555566555555";
textInput.setText(stringa);
}
Why:
The slash(/) and hyphen(-) are breaking characters, so it will naturally seek to break the lines at those points. That's how word wrap works, by looking for breaking chars and inserting new line characters at the last break spot that will fit.
Fix?
If you can measure the lines to see how many characters will fit on each line, you may be able to insert a zero-width space(U+200B) to force a line break at that spot. Not all fonts support this character, however, so this may not work on all devices.
Various answers to this question may help you if you're unable to use a zw-space, or if you're interested in auto-sizing in general.
I need help understanding how to accomplish math between different EditText views. I am not asking someone to write me the code but maybe explain what is involved to get this done.
I wanted to post a picture of this but as a new user I can not. Basicly I have a EditText for the following: Width, Length, Eave Height, Pitch.
I have ID's for all the TextViews I just dont know how to program the behind the scenes math involved to make them work. I do have the equations needed to perform the math just not sure where and how to put them in java.
Basicly I need the user to enter a number in each of the top 4 boxes. I need to use an equation to generate the answer that will be displayed in the "SQFT" box. The user will also input a number in a cost box which will generat a "Total" that needs to be displayed in a separate TextView.
Any help would be appreciated, even if it is to point me in a direction of a tutorial to get me started. Thanks for your help.
Just to show what type of math I need to use, below is the equation I use for excel to calulate.
(length+width)*(Eave+1)*2 + (((width/2)/12*Pitch)*(width/2)*2)
I'm not sure if you don't know how to extract the numbers entered in the EditTexts, how to actually do the math calculation, how to let the user initiate the calculate or how to present it.
I created a small demo that has 2 EditTexts, and a TextView that displays the sum of the numbers entered. The user does not need to press any buttons to perform the calculation, it is performed automatically every time the user updates the text (I assumed this is what you wanted).
Please note this code is not good code, it uses lots of internal anonymous classes etc but it supposed to demonstrate the mechanics of how to do this.
This is the main.xml layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<EditText
android:id="#+id/a"
android:hint="input a"
android:inputType="number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:minWidth="60dp"/>
<EditText
android:id="#+id/b"
android:hint="input b"
android:inputType="number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:minWidth="60dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="a+b = " />
<TextView
android:id="#+id/total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp" />
</LinearLayout>
And this is the sample Activity:
package com.example;
import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.widget.EditText;
import android.widget.TextView;
public class SumActivity extends Activity
{
private int a;
private int b;
private TextView totalOutput;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
EditText inputA = (EditText) findViewById(R.id.a);
EditText inputB = (EditText) findViewById(R.id.b);
totalOutput = (TextView) findViewById(R.id.total);
inputA.addTextChangedListener(new TextChangedListener()
{
#Override
public void numberEntered(int number)
{
a = number;
updateTotal();
}
});
inputB.addTextChangedListener(new TextChangedListener()
{
#Override
public void numberEntered(int number)
{
b = number;
updateTotal();
}
});
}
private void updateTotal()
{
int total = a + b; // This is where you apply your function
totalOutput.setText("" + total); // need to do that otherwise int will
// be treated as res id.
}
private abstract class TextChangedListener implements TextWatcher
{
public abstract void numberEntered(int number);
#Override
public void afterTextChanged(Editable s)
{
String text = s.toString();
try
{
int parsedInt = Integer.parseInt(text);
numberEntered(parsedInt);
} catch (NumberFormatException e)
{
Log.w(getPackageName(), "Could not parse '" + text + "' as a number", e);
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
}
}
}
I have a TextView that is still taking up space when there is no text to display. This happens only on OS 1.6.
When my app runs on 2.2, the height of the TextView collapses so that it doesn't take up any space.
Is there some property I can set in TextView to because it to collapse or disappear when no text is set? Here is my XML code.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:layout_marginTop="3dp"
android:layout_marginRight="3dp"
android:background="#ff737373"
android:padding="3dp"
android:minWidth="64dp" >
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:tag="tabImage"></ImageView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:tag="tabCaption"
android:textColor="#ffd9d9d9" />
</LinearLayout>
If you want to make a textview disappear if its text is null then use android:visibility or programatically use textview.setVisibility(View.INVISIBLE); or textview.setVisibility(View.GONE);.
for what you asking, you have to use TextWatcher, and then when the text is empty just make the TextView disappear:
your_text_view.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable s) {
if(your_text_view.getText().toString().equals("")){
your_text_view.setVisibility(View.GONE);
}
}
});
and any time you want to change the Text in it, just use your_text_view.setVisibility(View.VISIBLE); just before you set the new text to it, and if the new text will be empty it will not be shown as it will disappear before you even notice, and in the case it is already VISIBLE, this line won't make any harm or affection.
just make sure to declare your TextView as a general variable in order to be able to use it within the TextWatcher.
textview.setVisibility(View.INVISIBLE);
textview.setHeight(0);
Just to give a more complete Answer. You can give the TextView AutoCollapse capabilities by checking what text is being displayed whenever it is changed via TextChangedListener
I would simply use
.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) {
if(charSequence.length()>0)
textView.setVisibility(View.VISIBLE);
else textView.setVisibility(View.INVISIBLE);
}
#Override
public void afterTextChanged(Editable editable) {
}
});
and it now has the functionality that you are looking for.
I haven't encountered many things in android UI that don't have a viable change listener, this is applicable for most issues of adding functionality to views.
I want to limit input in the EditText of all symbols except figures, "?" And "*". How I am able to do it?
If you also have a maximum strict length of your string, you can use a mask. I'm not sure that it's the right solution, but it's the easiest one. An easy way use a mask in your Android programs in Android Studio is to use MaskedEditText library (GitHub link).
I can not understand what does mean: figures, "?" And "", so I suppose just "?" and "". So the code is:
In your build.gradle:
compile 'ru.egslava:MaskedEditText:1.0.5'
And in your layout:
<br.com.sapereaude.maskedEditText.MaskedEditText
android:id="#+id/phone_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="phone"
android:typeface="monospace"
mask:allowed_chars="?*"
mask:mask="##########"
app:keep_hint="true"
/>
This code creates an EditText that can contain ONLY "?" and "*" and max length is 10. Feel free to ask your questions :-)
You could add a TextWatch via addTextChangedListener. afterTextChanged allows you to modify the text after it was modified.
(Keep in mind that there are many ways to modify a text field - entering text, auto-complete through IME, copy and paste). Handle those properly in the TextWatch.
By this, we can restrict the user to not type ? and *
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="#dimen/register_text_size"
android:layout_weight="1"
android:id="#+id/first_name"
android:padding="14dp"
android:digits="##$%^&()_-+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12"
android:singleLine="true"
android:hint="#string/first_name"/>
you can check your input from edittext.addTextChangeListener method.
etAdjustmentInput.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) {
//checking the length of input
if (etAdjustmentInput.getText().toString().trim().length()<=0){
// if length less then or equals 0 show warning or make button not clickable
tvAdjustmentInfoOk.setClickable(false);
tvAdjustmentInfoOk.setTextColor(getResources().getColor(R.color.time_color));
}
else {
// input length greater then 0 now check the input type according to your requirement
tvAdjustmentInfoOk.setClickable(true);
tvAdjustmentInfoOk.setTextColor(getResources().getColor(R.color.colorPrimaryDark));
if(s.equals("?")){
//do your task
}
else{ // whatever you want to tell the user
}
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
Inside onTextChanged method you can restrict the user to maximum length and also you can check the input type according to your requirement
Try this
From this code you can enter 0 to 9 digits and only two special character ? and *.
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/first_name"
android:digits="?*1234567890"
android:singleLine="true"
/>
public class MainActivity extends Activity {
private EditText editText;
private String blockCharacterSet = "?*";
private InputFilter filter = new InputFilter() {
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
if (source != null && !blockCharacterSet.contains(("" + source))) {
return "";
}
return null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.editText);
editText.setFilters(new InputFilter[] { filter });
}
}