Reputation: 614
I am dynamically creating an EditText within an AlertDialog and want to limit the number of lines shown. Currently, the EditText keeps expanding vertically with each carriage return. This results in the dialog buttons not being visible after a certain point. I have isolated the code down to the following :
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b = (Button) findViewById(R.id.button);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
EditText input = new EditText(v.getContext());
input.setLines(4);
//input.setMaxLines(4);
input.setSingleLine(false);
input.setGravity(Gravity.TOP);
//input.setVerticalScrollBarEnabled(true);
builder.setView(input);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) { }
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) { }
});
AlertDialog d = builder.create();
d.show();
}
});
}
}
I'd be happy to either a) Limit the number of lines of text OR b) Have a scrollbar appear beyond X lines.
I've tried setting a number of properties on the EditText including 'setMaxLines','setHeight' and 'setVerticalScrollBarEnabled' and neither of these work.
I realise there is some existing suggestions for similar issues, but none where the EditText is created dynamically and within an AlertDialog. Any help or suggestions would be appreciated.
Upvotes: 2
Views: 2063
Reputation: 614
As with Darshan's answer, I ended up extending the EditText, implementing the TextWatcher interface and looking to see when the number of lines exceeded the limit set. When it does, the saved cursor position/text is restored. See code below:
public class MaxEditText extends EditText implements TextWatcher {
private String saved;
private int positionSaved;
private int maxLines;
public MaxEditText(Context context, int maxLines) {
super(context);
this.maxLines = maxLines;
this.setLines(maxLines);
this.setSingleLine(false);
this.setGravity(Gravity.TOP);
this.addTextChangedListener(this);
}
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
saved = arg0.toString();
positionSaved = ((EditText) this).getSelectionStart();
}
@Override
public void afterTextChanged(Editable arg0) {
if (this.getLineCount() > maxLines)
{
this.setText(saved);
((EditText) this).setSelection(positionSaved-1);
}
}
}
It seems to me like a bit of a hack to have to 'undo' what is entered as opposed to preventing the text being entered in the first place, so if anyone has an alternative, please post it.
Upvotes: 0
Reputation: 3372
you can limit lines count in your LimitedEditText component
you can limit characters count in your LimitedEditText component
if you exceed the limit of characters or lines somewhere in the middle of text, cursor won't bring you to the end - it will stay where have you been.
Im turning off listener, because every call of setText() method would recursively call these 3 callback methods in case when user exceeded characters or lines limit.
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.EditText;
import android.widget.Toast;
/**
* EditText subclass created to enforce limit of the lines number in editable
* text field
*/
public class LimitedEditText extends EditText {
/**
* Max lines to be present in editable text field
*/
private int maxLines = 1;
/**
* Max characters to be present in editable text field
*/
private int maxCharacters = 50;
/**
* application context;
*/
private Context context;
public int getMaxCharacters() {
return maxCharacters;
}
public void setMaxCharacters(int maxCharacters) {
this.maxCharacters = maxCharacters;
}
@Override
public int getMaxLines() {
return maxLines;
}
@Override
public void setMaxLines(int maxLines) {
this.maxLines = maxLines;
}
public LimitedEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
}
public LimitedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
public LimitedEditText(Context context) {
super(context);
this.context = context;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
TextWatcher watcher = new TextWatcher() {
private String text;
private int beforeCursorPosition = 0;
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
//TODO sth
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
text = s.toString();
beforeCursorPosition = start;
}
@Override
public void afterTextChanged(Editable s) {
/* turning off listener */
removeTextChangedListener(this);
/* handling lines limit exceed */
if (LimitedEditText.this.getLineCount() > maxLines) {
LimitedEditText.this.setText(text);
LimitedEditText.this.setSelection(beforeCursorPosition);
}
/* handling character limit exceed */
if (s.toString().length() > maxCharacters) {
LimitedEditText.this.setText(text);
LimitedEditText.this.setSelection(beforeCursorPosition);
Toast.makeText(context, "text too long", Toast.LENGTH_SHORT)
.show();
}
/* turning on listener */
addTextChangedListener(this);
}
};
this.addTextChangedListener(watcher);
}
}
Upvotes: 2
Reputation: 10651
If you want to set a fixed number of lines you should do
setLines(int numOfLines);
If you want to set a limit to the number of lines which will be added on typing
setMaxLines(int limit);
And for additional information, you could set the limit to minimum number of lines using
setMinLines(int limit);
Upvotes: 2