I want to expand the view on clicking the + button and this + sign changes to - when the view expanded.Again when i click the - button the view should be shrink.
Inside the view i have some TextView field.Please anyone suggest me.I am new to android.
This answer solves the question.
public class ExpandableTextView extends TextView implements OnClickListener
{
private static final int MAX_LINES = 5;
private int currentMaxLines = Integer.MAX_VALUE;
public ExpandableTextView(Context context)
{
super(context);
setOnClickListener(this);
}
public ExpandableTextView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
setOnClickListener(this);
}
public ExpandableTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
setOnClickListener(this);
}
#Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter)
{
/* If text longer than MAX_LINES set DrawableBottom - I'm using '...' icon */
post(new Runnable()
{
public void run()
{
if (getLineCount()>MAX_LINES)
setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, R.drawable.icon_more_text);
else
setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
setMaxLines(MAX_LINES);
}
});
}
#Override
public void setMaxLines(int maxLines)
{
currentMaxLines = maxLines;
super.setMaxLines(maxLines);
}
/* Custom method because standard getMaxLines() requires API > 16 */
public int getMyMaxLines()
{
return currentMaxLines;
}
#Override
public void onClick(View v)
{
/* Toggle between expanded collapsed states */
if (getMyMaxLines() == Integer.MAX_VALUE)
setMaxLines(MAX_LINES);
else
setMaxLines(Integer.MAX_VALUE);
}
}
You can visible or gone particular layout on button click event at runtime like below code:
findViewById(R.id.yourButtonId).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mainView.setVisibility(View.GONE);
}
});
How can I get the caps lock state in Android using a hardware keyboard?
In pure Java it can be detected with
boolean isOn = Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_CAPS_LOCK);
But this does not work with Android...
Try This (didn't test it):
public class CustomEditText extends EditText{
public CustomEditText(Context context) {
super(context);
}
public CustomEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(event.isCapsLockOn()){
//Do what Ever
}
return super.onKeyDown(keyCode, event);
}
}
isCapsLockOn
You can use android:inputType="textCapSentences" in your editText, if you want to make the first letter, start with caps. There are other options also, if you want some different behaviour.
I don't think there is any Android API which can detect state of capslock. But i do have its alternative.
If you want to detect that whether CAPSLOCK is on or off, Its better to use TextWatcher for your EditText.
mEditText.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) {
String character = s.toString();
/*
Matche entered character with Rajex wheter its capital or small
*/
if (Pattern.matches("[a-z]",character)) {
Log.e("","CapsLock is OFF");
}
else if (Pattern.matches("[A-Z]",character)){
Log.e("", "CapsLock is ON");
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
The following code i am using for getting status of typing in Text Changes function.....
mEditText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
try {
session.typing();
} catch (OmegleException e) {
e.printStackTrace();
}
}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
public void onTextChanged(CharSequence s, int start,
int before, int count) {
}
});
try something like this -guess is a chat app right so -
final Random ran = new Random();
mEditText.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) {
if(start %2 ==0 && ran.nextBoolean()){
try {
session.typing();
} catch (OmegleException e) {
e.printStackTrace();
}
}
});
Edit
b4 i do your final request, do you mind runing session.typing on new Thread, like this
new Thread(new Runnable() {
#Override
public void run() {
try {
session.typing();
} catch (OmegleException e) {
e.printStackTrace();
}
}
}).start();
Edit 2
on first letter input
mEditText.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) {
if(start ==1){
try {
session.typing();
} catch (OmegleException e) {
e.printStackTrace();
}
}
});
It can be fixed by changing the EditText width to 0dp using weighted widths to
match/fill the parent.
I don't know for sure why this was occurring, however I believe it is because when the width of the EditText is set to wrap content it will adjust/redraw itself so that everything fits. So by making the EditText have a fixed width, this redraw is no longer required.
What does the "0dp" signify for the width? That it should take up all the available space?
yes, it will. The layout_weight tag will do that.
<EditText
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="5"/>
For you problem i have one advice for you :
Set your status as typing till user don't press done button on keyboard.
editText.setOnEditorActionListener(new EditText.OnEditorActionListener() {
#Override
public boolean onEditorAction(EditText v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
//do here your stuff f
return true;
}
return false;
} });
How can I detect delete (backspace) key event for a editText? I've tried using TextWatcher, but when the editText is empty, when I press delete key, nothing happens. I want to detect delete key press foe an editText even if it has no text.
NOTE: onKeyListener doesn't work for soft keyboards.
You can set OnKeyListener for you editText so you can detect any key press
EDIT: A common mistake we are checking KeyEvent.KEYCODE_BACK for backspace, but really it is KeyEvent.KEYCODE_DEL (Really that name is very confusing! )
editText.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
//You can identify which key pressed by checking keyCode value with KeyEvent.KEYCODE_
if(keyCode == KeyEvent.KEYCODE_DEL) {
//this is for backspace
}
return false;
}
});
It's been a while since you asked but I just had the same issue. As already mentioned by Estel the problem with key listeners is that they only work with hardware keyboards. To do this with an IME (soft keyboard), the solution is a bit more elaborate.
The single method we actually want to override is sendKeyEvent in the EditText's InputConnection class. This method is called when key events occur in an IME. But in order to override this, we need to implement a custom EditText which overrides the onCreateInputConnection method, wrapping the default InputConnection object in a proxy class! :|
Sounds complicated, but here's the simplest example I could contrive:
public class ZanyEditText extends EditText {
private Random r = new Random();
public ZanyEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ZanyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ZanyEditText(Context context) {
super(context);
}
public void setRandomBackgroundColor() {
setBackgroundColor(Color.rgb(r.nextInt(256), r.nextInt(256), r
.nextInt(256)));
}
#Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
return new ZanyInputConnection(super.onCreateInputConnection(outAttrs),
true);
}
private class ZanyInputConnection extends InputConnectionWrapper {
public ZanyInputConnection(InputConnection target, boolean mutable) {
super(target, mutable);
}
#Override
public boolean sendKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
ZanyEditText.this.setRandomBackgroundColor();
// Un-comment if you wish to cancel the backspace:
// return false;
}
return super.sendKeyEvent(event);
}
}
}
The line with the call to setRandomBackgroundColor is where my special backspace action occurs. In this case, changing the EditText's background colour.
If you're inflating this from XML remember to use the full package name as the tag:
<cc.buttfu.test.ZanyEditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/somefield"
></cc.buttfu.test.ZanyEditText>
This is just an addition to Idris's answer, adding in the override to deleteSurroundingText as well. I found more info on that here: Android: Backspace in WebView/BaseInputConnection
package com.elavon.virtualmerchantmobile.utils;
import java.util.Random;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;
import android.widget.EditText;
public class ZanyEditText extends EditText {
private Random r = new Random();
public ZanyEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ZanyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ZanyEditText(Context context) {
super(context);
}
public void setRandomBackgroundColor() {
setBackgroundColor(Color.rgb(r.nextInt(256), r.nextInt(256), r
.nextInt(256)));
}
#Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
return new ZanyInputConnection(super.onCreateInputConnection(outAttrs),
true);
}
private class ZanyInputConnection extends InputConnectionWrapper {
public ZanyInputConnection(InputConnection target, boolean mutable) {
super(target, mutable);
}
#Override
public boolean sendKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
ZanyEditText.this.setRandomBackgroundColor();
// Un-comment if you wish to cancel the backspace:
// return false;
}
return super.sendKeyEvent(event);
}
#Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
// magic: in latest Android, deleteSurroundingText(1, 0) will be called for backspace
if (beforeLength == 1 && afterLength == 0) {
// backspace
return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
&& sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
}
return super.deleteSurroundingText(beforeLength, afterLength);
}
}
}
Here is my easy solution, which works for all the API's:
private int previousLength;
private boolean backSpace;
// ...
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
previousLength = s.length();
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
backSpace = previousLength > s.length();
if (backSpace) {
// do your stuff ...
}
}
UPDATE 17.04.18 .
As pointed out in comments, this solution doesn't track the backspace press if EditText is empty (the same as most of the other solutions).
However, it's enough for most of the use cases.
P.S. If I had to create something similar today, I would do:
public abstract class TextWatcherExtended implements TextWatcher {
private int lastLength;
public abstract void afterTextChanged(Editable s, boolean backSpace);
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
lastLength = s.length();
}
#Override
public void afterTextChanged(Editable s) {
afterTextChanged(s, lastLength > s.length());
}
}
Then just use it as a regular TextWatcher:
editText.addTextChangedListener(new TextWatcherExtended() {
#Override
public void afterTextChanged(Editable s, boolean backSpace) {
// Here you are! You got missing "backSpace" flag
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Do something useful if you wish.
// Or override it in TextWatcherExtended class if want to avoid it here
}
});
I sent 2 days to find a solution and I figured out a working one :) (on soft keys)
public TextWatcher textWatcher = 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) {
if (count == 0) {
//Put your code here.
//Runs when delete/backspace pressed on soft key (tested on htc m8)
//You can use EditText.getText().length() to make if statements here
}
}
#Override
public void afterTextChanged(Editable s) {
}
}
After add the textwatcher to your EditText:
yourEditText.addTextChangedListener(textWatcher);
I hope it works on another android devices too (samsung, LG, etc).
My simple solution which works perfectly. You should to add a flag. My code snippet:
editText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (after < count) {
isBackspaceClicked = true;
} else {
isBackspaceClicked = false;
}
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) { }
#Override
public void afterTextChanged(Editable s) {
if (!isBackspaceClicked) {
// Your current code
} else {
// Your "backspace" handling
}
}
Example of creating EditText with TextWatcher
EditText someEdit=new EditText(this);
//create TextWatcher for our EditText
TextWatcher1 TW1 = new TextWatcher1(someEdit);
//apply our TextWatcher to EditText
someEdit.addTextChangedListener(TW1);
custom TextWatcher
public class TextWatcher1 implements TextWatcher {
public EditText editText;
//constructor
public TextWatcher1(EditText et){
super();
editText = et;
//Code for monitoring keystrokes
editText.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_DEL){
editText.setText("");
}
return false;
}
});
}
//Some manipulation with text
public void afterTextChanged(Editable s) {
if(editText.getText().length() == 12){
editText.setText(editText.getText().delete(editText.getText().length() - 1, editText.getText().length()));
editText.setSelection(editText.getText().toString().length());
}
if (editText.getText().length()==2||editText.getText().length()==5||editText.getText().length()==8){
editText.setText(editText.getText()+"/");
editText.setSelection(editText.getText().toString().length());
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after){
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
}
for some one who's using Kotlin
addOnTextChanged is not flexible enought to handle some cases (ex: detect if user press delete when edit text was empty)
setOnkeyListener worked even soft keyboard or hardkeyboard! but just on some devices. In my case, it work on Samsung s8 but not work on Xiaomi mi8 se.
if you using kotlin, you can use crossline function doOnTextChanged, it's the same as addOnTextChanged but callback is triggered even edit text was empty.
NOTE: doOnTextChanged is a part of Android KTX library
Based on #Jiff ZanyEditText here is WiseEditText with setSoftKeyListener(OnKeyListener)
package com.locopixel.seagame.ui.custom;
import java.util.Random;
import android.content.Context;
import android.graphics.Color;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;
public class WiseEditText extends AppCompatEditText {
private Random r = new Random();
private OnKeyListener keyListener;
public WiseEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public WiseEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WiseEditText(Context context) {
super(context);
}
#Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
return new MyInputConnection(super.onCreateInputConnection(outAttrs),
true);
}
private class MyInputConnection extends InputConnectionWrapper {
public MyInputConnection(InputConnection target, boolean mutable) {
super(target, mutable);
}
#Override
public boolean sendKeyEvent(KeyEvent event) {
if (keyListener != null) {
keyListener.onKey(WiseEditText.this,event.getKeyCode(),event);
}
return super.sendKeyEvent(event);
}
#Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
// magic: in latest Android, deleteSurroundingText(1, 0) will be called for backspace
if (beforeLength == 1 && afterLength == 0) {
// backspace
return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
&& sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
}
return super.deleteSurroundingText(beforeLength, afterLength);
}
}
public void setSoftKeyListener(OnKeyListener listener){
keyListener = listener;
}
}
This seems to be working for me :
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (before - count == 1) {
onBackSpace();
} else if (s.subSequence(start, start + count).toString().equals("\n")) {
onNewLine();
}
}
I am also faced same issue in Dialog.. because I am using setOnKeyListener.. But I set default return true. After change like below code it working fine for me..
mDialog.setOnKeyListener(new Dialog.OnKeyListener() {
#Override
public boolean onKey(DialogInterface arg0, int keyCode,
KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
mDialog.dismiss();
return true;
}
return false;//this line is important
}
});
My problem was, that I had custom Textwatcher, so I didn't want to add OnKeyListener to an EditText as well as I didn't want to create custom EditText. I wanted to detect if backspace was pressed in my afterTextChanged method, so I shouldn't trigger my event.
This is how I solved this. Hope it would be helpful for someone.
public class CustomTextWatcher extends AfterTextChangedTextWatcher {
private boolean backspacePressed;
#Override
public void afterTextChanged(Editable s) {
if (!backspacePressed) {
triggerYourEvent();
}
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
super.onTextChanged(s, start, before, count);
backspacePressed = count == 0; //if count == 0, backspace is pressed
}
}
I have tested #Jeff's solution on version 4.2, 4.4, 6.0. On 4.2 and 6.0, it works well. But on 4.4, it doesn't work.
I found an easy way to work around this problem. The key point is to insert an invisible character into the content of EditText at the begining, and don't let user move cursor before this character. My way is to insert a white-space character with an ImageSpan of Zero Width on it. Here is my code.
#Override
public void afterTextChanged(Editable s) {
String ss = s.toString();
if (!ss.startsWith(" ")) {
int selection = holder.editText.getSelectionEnd();
s.insert(0, " ");
ss = s.toString();
holder.editText.setSelection(selection + 1);
}
if (ss.startsWith(" ")) {
ImageSpan[] spans = s.getSpans(0, 1, ImageSpan.class);
if (spans == null || spans.length == 0) {
s.setSpan(new ImageSpan(getResources().getDrawable(R.drawable.zero_wdith_drawable)), 0 , 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
And we need custom an EditText which has a SelectionChangeListener
public class EditTextSelectable extends android.support.v7.widget.AppCompatEditText {
public interface OnSelectChangeListener {
void onSelectChange(int start, int end);
}
private OnSelectChangeListener mListener;
public void setListener(OnSelectChangeListener listener) {
mListener = listener;
}
...constructors...
#Override
protected void onSelectionChanged(int selStart, int selEnd) {
if (mListener != null) {
mListener.onSelectChange(selStart, selEnd);
}
super.onSelectionChanged(selStart, selEnd);
}
}
And the last step
holder.editText.setListener(new EditTextSelectable.OnSelectChangeListener() {
#Override
public void onSelectChange(int start, int end) {
if (start == 0 && holder.editText.getText().length() != 0) {
holder.editText.setSelection(1, Math.max(1, end));
}
}
});
And now, we are done~ We can detect backspace key event when EditText has no actual content, and user will know nothing about our trick.
This question may be old but the answer is really simple using a TextWatcher.
int lastSize=0;
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
//2. compare the old length of the text with the new one
//3. if the length is shorter, then backspace was clicked
if (lastSize > charSequence.length()) {
//4. Backspace was clicked
//5. perform action
}
//1. get the current length of of the text
lastSize = charSequence.length();
}
I have found a really simple solution which works with a soft keyboard.
override fun onTextChanged(text: CharSequence?, start: Int, before: Int, count: Int) {
text?.let {
if(count < before) {
Toast.makeText(context, "backspace pressed", Toast.LENGTH_SHORT).show()
// implement your own code
}
}
}
Belated but it may help new visitors, use TextWatcher() instead will help alot and also it will work for both soft and hard keyboard as well.
editText.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) {
//Here it means back button is pressed and edit text is now empty
} else {
//Here edit text has some text
}
}
#Override
public void afterTextChanged(Editable editable) {
}
});
You could set a key listener on the activity, and in the callback method, you could detect
which key the user hit. The code below is for your reference. Hope it helps.
//after user hits keys, this method would be called.
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (editText.isFocused()) {
switch (keyCode) {
case KeyEvent.KEYCODE_DEL: //delete key
Log.i("INFO", "delete key hit"); //you should see this log in ddms after you hit delete key
break;
}
}
return super.onKeyUp(keyCode, event);
}