Listen any key pressed on edittext - java

I am having a question, how to handle EditText when I press any key from mobile, then a Toast will appear with its content: "Key is pressed".
I used:
edittext.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
while(event.getCharacters()!=null )
........
}
});
but it is not ok.
Can anybody help me?

Try the following ---
edittext.setOnKeyListener(new EditText.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(event.getAction()==KeyEvent.ACTION_DOWN)
{
//Do anything with editTextContent
String editTextContent = edittext.getText().toString();
Toast.makeText(getApplicationContext(),
editTextContent +": Key is pressed", Toast.LENGTH_LONG).show();
}
});

This is my function on my application,when i entered a text in edittext field and entered,then Toast will appear with the entered content:
private Bitmap ProcessingBitmap(){
Bitmap bm1 = null;
Bitmap newBitmap = null;
try {
bm1 = BitmapFactory.decodeStream(
getContentResolver().openInputStream(selectedImage));
Config config = bm1.getConfig();
if(config == null){
config = Bitmap.Config.ARGB_8888;
}
newBitmap = Bitmap.createBitmap(bm1.getWidth(), bm1.getHeight(), config);
Canvas newCanvas = new Canvas(newBitmap);
newCanvas.drawBitmap(bm1, 0, 0, null);
String captionString = editTextCaption.getText().toString();
editTextCaption.getText().clear();
if(captionString != null){
Paint paintText = new Paint(Paint.ANTI_ALIAS_FLAG);
paintText.setColor(Color.GREEN);
paintText.setTextSize(50);
paintText.setStyle(Style.FILL);
paintText.setShadowLayer(10f, 10f, 10f, Color.BLACK);
Rect rectText = new Rect();
paintText.getTextBounds(captionString, 0, captionString.length(), rectText);
newCanvas.drawText(captionString, 0, rectText.height(), paintText);
Toast.makeText(getApplicationContext(), "drawText: " + captionString, Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(), "caption empty!", Toast.LENGTH_LONG).show();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return newBitmap;
}
OR use it on this way hope it's help:
edittext.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
while(event.getCharacters()!=null )
String captionString = edittext.getText().toString();
Toast.makeText(getApplicationContext(), "drawText: " + captionString, Toast.LENGTH_LONG).show();
}
});
i put the comments but it's not show,i don't know why,ok try this hope it's worked,also it's working fine on my side.
edittext.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
while(event.getCharacters()!=null )
String captionString = edittext.getText().toString();
if(captionString != null){
Toast.makeText(getApplicationContext(), "drawText: " + captionString, Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(), "caption empty!", Toast.LENGTH_LONG).show();
}
}
});

Related

Write variable from AlertDialog

So I'm doing an app what I'm trying to use a AlertDialog to write a variable on a PLC. I want to make it so that every time you click the button the var increments by 1. It almost works other than it only execute once. So when I click the Speed Up button it increments, but if I click it again, it doesn't increment again. If I then select the Speed Down button it will decrease the value by 1, (as it's suppose to) but once again, it won't execute again if I click the button again. I'm very new to this type of programming. Any help would be appreciated though!
public void ShowPopUpMenus(View v) {
final AlertDialog.Builder sayWindows = new AlertDialog.Builder(WritesActivity.this);
sayWindows.setPositiveButton("Speed Up", null);
sayWindows.setNegativeButton("Close", null);
sayWindows.setNeutralButton("speed Down", null);
//sayWindows.setAdapter(listWords, null);
//sayWindows.setView(saySomething);
sayWindows.setTitle(" Machine Speed"); //Title!
final AlertDialog mAlertDialog = sayWindows.create();
mAlertDialog.setMessage(" " + sMachineSpeedTemp); //Center Text, Probably not the correct way to do this. :)
mAlertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(final DialogInterface dialog) {
//while (bDummy== false) {
Button button_Speed_Up = mAlertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
button_Speed_Up.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
MlpiConnection device = m_app.getDevice();
device.connect("192.168.0.5");
if (device.isConnected()) {
sMachineSpeedTemp = (device.logic().readVariableBySymbolAsString("Application.UserVarGlobal.sMachineSpeed_gb"));
iMachineSpeedTemp = Integer.parseInt(sMachineSpeedTemp);
iMachineSpeedTemp++;
device.logic().writeVariableBySymbolAsString("Application.UserVarGlobal.sMachineSpeed_gb", sMachineSpeedTemp);
sMachineSpeedTemp = iMachineSpeedTemp.toString();
mAlertDialog.setMessage("" + sMachineSpeedTemp);
}
else
{
mAlertDialog.setMessage("bad connection");
}
}
catch (Exception e) {
Context c = v.getContext();
Toast.makeText(c, e + "Connection Error UP", Toast.LENGTH_LONG).show();
}
}
});
Button button_Speed_Down = mAlertDialog.getButton(AlertDialog.BUTTON_NEUTRAL);
button_Speed_Down.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
MlpiConnection device = m_app.getDevice();
device.connect("192.168.0.5");
if (device.isConnected()) {
sMachineSpeedTemp = (device.logic().readVariableBySymbolAsString("Application.UserVarGlobal.sMachineSpeed_gb"));
iMachineSpeedTemp = Integer.parseInt(sMachineSpeedTemp);
iMachineSpeedTemp--;
device.logic().writeVariableBySymbolAsString("Application.UserVarGlobal.sMachineSpeed_gb", sMachineSpeedTemp);
sMachineSpeedTemp = iMachineSpeedTemp.toString();
mAlertDialog.setMessage(sMachineSpeedTemp);
mAlertDialog.setMessage("" + sMachineSpeedTemp);
}
else
{
mAlertDialog.setMessage("bad connection");
}
} catch (Exception e) {
Context c = v.getContext();
Toast.makeText(c, e + "Connection Error Down", Toast.LENGTH_LONG).show();
}
}
});
}
});
mAlertDialog.show();
}
I think you are executing the code below every time you click on the button. This line iMachineSpeedTemp = Integer.parseInt(sMachineSpeedTemp); will override the value of iMachineSpeedTemp and increment it once so you will keep getting the same value.`
if (device.isConnected()) {
sMachineSpeedTemp = device.logic().readVariableBySymbolAsString("Application.UserVarGlobal.sMachineSpeed_gb"));
iMachineSpeedTemp = Integer.parseInt(sMachineSpeedTemp);
iMachineSpeedTemp++;
device.logic().writeVariableBySymbolAsString("Application.UserVarGlobal.sMachineSpeed_gb", sMachineSpeedTemp);
sMachineSpeedTemp = iMachineSpeedTemp.toString();
mAlertDialog.setMessage("" + sMachineSpeedTemp);
}
A possible solution is to a boolean flag
public class MyClass{
private int iMachineSpeedTemp;
private boolean isConnected = false;
}
Then you can check if isConnected is true
if (device.isConnected()) {
if(isConnected){
iMachineSpeedTemp++
}else{
sMachineSpeedTemp = device.logic().readVariableBySymbolAsString("Application.UserVarGlobal.sMachineSpeed_gb"));
iMachineSpeedTemp = Integer.parseInt(sMachineSpeedTemp);
iMachineSpeedTemp++;
isConnected = true;
}
device.logic().writeVariableBySymbolAsString("Application.UserVarGlobal.sMachineSpeed_gb", sMachineSpeedTemp);
sMachineSpeedTemp = iMachineSpeedTemp.toString();
mAlertDialog.setMessage("" + sMachineSpeedTemp);
}
public void onClick(View v) {
try {
MlpiConnection device = m_app.getDevice();
device.connect("192.168.0.5");
if (device.isConnected()) {
sMachineSpeedTemp = device.logic().readVariableBySymbolAsString("Application.UserVarGlobal.sMachineSpeed_gb");
iMachineSpeedTemp = Integer.parseInt(sMachineSpeedTemp);
iMachineSpeedTemp++;
sMachineSpeedTemp = Integer.toString(iMachineSpeedTemp);
device.logic().writeVariableBySymbolAsString("Application.UserVarGlobal.sMachineSpeed_gb", sMachineSpeedTemp);
mAlertDialog.setMessage(" " + sMachineSpeedTemp);
}
}

Send button is sending data if there are error inside Edittext in Android

i have used two edit text boxes where i have done validation for both the edittext boxes for email and confirm email address i have used text matcher and validation is working fine for me no issues when i checked it the data entered in the edittext is going inside database when i click the send button if there are error as well how to make the button disable when there will be error in any of the text boxes after correcting the error it has to deploy the data entered into database else it has to disable the button
i need to enter some thing to block the send button
I have done the validation here for edittext3 and edittext4 so if there any errors in this button has to disable where i must include
send.setEnabled(false);
send.setEnabled(true);
i must include this above method in this code
edittext3.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) {
Is_Valid_Email_Address(edittext3);
}
public void Is_Valid_Email_Address(EditText edittext3) {
if (edittext3.getText().toString() == null) {
edittext3.setError("Invalid Email Address");
valid_email = null;
} else if (isEmailValid(edittext3.getText().toString()) == false) {
edittext3.setError("Invalid Email Address");
valid_email = null;
} else if(edittext3.length() == 0 || edittext3.equals("") || edittext3 == null || "".equals(edittext3.getText().toString())) {
valid_email = null;
}else {
valid_email = edittext3.getText().toString();
}
}
});
edittext4.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) {
Is_Valid_Confirm_Address(edittext4);
}
public void Is_Valid_Confirm_Address(EditText edittext4) {
if (edittext4.getText().toString() == null) {
edittext4.setError("Invalid Email Address");
valid_confirm = null;
} else if (isEmailValid(edittext4.getText().toString()) == false) {
edittext4.setError("Invalid Email Address");
valid_confirm = null;
} else if (edittext4.getText().toString().equals(edittext3.getText().toString())) {
valid_confirm = edittext4.getText().toString();
} else if(edittext4.length() == 0 || edittext4.equals("") || edittext4 == null || "".equals(edittext4.getText().toString())) {
valid_confirm = null;
} else {
edittext4.setError("Confirm Email is Not Matching");
valid_confirm = null;
}
}
});
//if there are any errors then button must become disable or enable to add it into database
Button send= (Button)findViewById(R.id.send_email);
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String email = edittext3.getText().toString();
String confirm = edittext4.getText().toString();
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("email_address",email));
nameValuePairs.add(new BasicNameValuePair("confirm_email_address",confirm));
try
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://192.168.1.132/Android_App/Sendata.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
Log.e("log_tag", "connection success ");
Toast.makeText(getApplicationContext(), "contact you shortly.", Toast.LENGTH_LONG).show();
}
catch(Exception e)
{
Log.e("log_tag", "Error in http connection "+e.toString());
Toast.makeText(getApplicationContext(), "Connection fail", Toast.LENGTH_SHORT).show();
}
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
Intent i = new Intent(getBaseContext(),SecondActivity.class);
startActivity(i);
}
is.close();
result=sb.toString();
}
catch(Exception e)
{
Log.e("log_tag", "Error converting result "+e.toString());
}
try
{
JSONObject json_data = new JSONObject(result);
CharSequence w= (CharSequence) json_data.get("result");
Toast.makeText(getApplicationContext(), w, Toast.LENGTH_SHORT).show();
}
catch(JSONException e)
{
Log.e("log_tag", "Error parsing data "+e.toString());
Toast.makeText(getApplicationContext(), "JsonArray fail", Toast.LENGTH_SHORT).show();
}
}
});
}
private boolean isEmailValid(String email) {
return android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches();
}
does anyone know please help me thanks in advance
public void afterTextChanged(Editable s) {
if(Is_Valid_Email_Address(edittext3.getText().toString())){
send.setEnabled(true);
}else{
send.setEnabled(false);
}
}
Maybe try this? Apply it for edittext4 too.
Try this way.

The app crashes when I click on the "Done" button on numeric keyboard

I have this code:
final EditText edC = (EditText) findViewById(R.id.etC);
final String creditsS = edC.getText().toString().trim();
final TextView tvD = (TextView) findViewById(R.id.tvDisplay);
tvD.setText("Enter amount of credits");
edC.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
int credits = Integer.parseInt(creditsS);
if (actionId == EditorInfo.IME_ACTION_DONE) {
tvD.setText("Your amount of credits" + credits);
return true;
}
return false;
}
});
and when I click the "Done" button, the app crashes. I don't understand where is the problem. Please help? Thanks!!!
Change your code to:
final EditText edC = (EditText) findViewById(R.id.etC);
final TextView tvD = (TextView) findViewById(R.id.tvDisplay);
tvD.setText("Enter amount of credits");
edC.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
String creditsS = edC.getText().toString().trim();
int credits = Integer.parseInt(creditsS);
if (actionId == EditorInfo.IME_ACTION_DONE) {
tvD.setText("Your amount of credits" + credits);
return true;
}
return false;
}
});
It's crashing because you're getting the value from edC before there is any value, so it's trying to parse an empty string and it crashes with NumberFormatException.

Android: ClickableSpan in clickable TextView

I have a textview that can contain clickable links. When one of this links is clicked, I want to start an activity. This works fine, but it should also be possible to click the whole textview and start another activity.
So that's my current solution:
TextView tv = (TextView)findViewById(R.id.textview01);
Spannable span = Spannable.Factory.getInstance().newSpannable("test link span");
span.setSpan(new ClickableSpan() {
#Override
public void onClick(View v) {
Log.d("main", "link clicked");
Toast.makeText(Main.this, "link clicked", Toast.LENGTH_SHORT).show();
} }, 5, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(span);
tv.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.d("main", "textview clicked");
Toast.makeText(Main.this, "textview clicked", Toast.LENGTH_SHORT).show();
}
});
tv.setMovementMethod(LinkMovementMethod.getInstance());
The problem is, that when I set an OnClickListener, everytime I click on a link first the listener for the whole textview and then the one for the ClickableSpan is called.
Is there a way to prevent android from calling the listener for the whole textview, when a link is clicked? Or to decide in the listener for the whole view, if a link was clicked or not?
Found a workaround that is quite straight forward. Define ClickableSpan on all the text areas that are not part of the links and handle the click on them as if the text view was clicked:
TextView tv = (TextView)findViewById(R.id.textview01);
Spannable span = Spannable.Factory.getInstance().newSpannable("test link span");
span.setSpan(new ClickableSpan() {
#Override
public void onClick(View v) {
Log.d("main", "link clicked");
Toast.makeText(Main.this, "link clicked", Toast.LENGTH_SHORT).show();
} }, 5, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// All the rest will have the same spannable.
ClickableSpan cs = new ClickableSpan() {
#Override
public void onClick(View v) {
Log.d("main", "textview clicked");
Toast.makeText(Main.this, "textview clicked", Toast.LENGTH_SHORT).show();
} };
// set the "test " spannable.
span.setSpan(cs, 0, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// set the " span" spannable
span.setSpan(cs, 6, span.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(span);
tv.setMovementMethod(LinkMovementMethod.getInstance());
Hope this helps (I know this thread is old, but in case anyone sees it now...).
This is a quite easy solution.. This worked for me
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ClassroomLog.log(TAG, "Textview Click listener ");
if (textView.getSelectionStart() == -1 && textView.getSelectionEnd() == -1) {
// do your code here this will only call if its not a hyperlink
}
}
});
Matthew suggested subclassing TextView and with that hint a came up with a rather ugly workaround. But it works:
I've created a "ClickPreventableTextView" which I use when I have clickablespans in a TextView that should be clickable as a whole.
In its onTouchEvent method this class calls the onTouchEvent method of MovementMethod before calling onTouchEvent on its base TextView class. So it is guaranted, that the Listener of the clickablespan will be invoked first. And I can prevent invoking the OnClickListener for the whole TextView
/**
* TextView that allows to insert clickablespans while whole textview is still clickable<br>
* If a click an a clickablespan occurs, click handler of whole textview will <b>not</b> be invoked
* In your span onclick handler you first have to check whether {#link ignoreSpannableClick} returns true, if so just return from click handler
* otherwise call {#link preventNextClick} and handle the click event
* #author Lukas
*
*/
public class ClickPreventableTextView extends TextView implements OnClickListener {
private boolean preventClick;
private OnClickListener clickListener;
private boolean ignoreSpannableClick;
public ClickPreventableTextView(Context context) {
super(context);
}
public ClickPreventableTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ClickPreventableTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public boolean onTouchEvent(MotionEvent event) {
if (getMovementMethod() != null)
getMovementMethod().onTouchEvent(this, (Spannable)getText(), event);
this.ignoreSpannableClick = true;
boolean ret = super.onTouchEvent(event);
this.ignoreSpannableClick = false;
return ret;
}
/**
* Returns true if click event for a clickable span should be ignored
* #return true if click event should be ignored
*/
public boolean ignoreSpannableClick() {
return ignoreSpannableClick;
}
/**
* Call after handling click event for clickable span
*/
public void preventNextClick() {
preventClick = true;
}
#Override
public void setOnClickListener(OnClickListener listener) {
this.clickListener = listener;
super.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (preventClick) {
preventClick = false;
} else if (clickListener != null)
clickListener.onClick(v);
}
}
The listener for the clickable span now looks like that
span.setSpan(new ClickableSpan() {
#Override
public void onClick(View v) {
Log.d("main", "link clicked");
if (widget instanceof ClickPreventableTextView) {
if (((ClickPreventableTextView)widget).ignoreSpannableClick())
return;
((ClickPreventableTextView)widget).preventNextClick();
}
Toast.makeText(Main.this, "link clicked", Toast.LENGTH_SHORT).show();
} }, 5, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
For me the main disadvantage is, that now getMovementMethod().onTouchEvent will be called twice (TextView calls that method in it's onTouchEvent method). I don't know if this has any side effects, atm it works as expected.
The code is work for me and that is from source code of LinkMovementMethod
tv.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
TextView tv = (TextView) v;
if (event.action == MotionEvent.ACTION_UP) {
int x = (int) event.getX();
int y = (int) event.getY();
Layout layout = tv.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = contentSpan.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
link[0].onClick(tv);
} else {
//do other click
}
}
return true;
}
});
Solved something very similar in a very nice way.
I wanted to have text that has a link which is clickable!! and i wanted to be able to press the text Where there is no link and have a on click listener in it.
I took the LinkMovementMethod from grepcode and changed it a little Copy and past this class and copy the bottom and it will work :
import android.text.Layout;
import android.text.NoCopySpan;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.MovementMethod;
import android.text.method.ScrollingMovementMethod;
import android.text.style.ClickableSpan;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
public class
CustomLinkMovementMethod
extends ScrollingMovementMethod
{
private static final int CLICK = 1;
private static final int UP = 2;
private static final int DOWN = 3;
public abstract interface TextClickedListener {
public abstract void onTextClicked();
}
TextClickedListener listener = null;
public void setOnTextClickListener(TextClickedListener listen){
listener = listen;
}
#Override
public boolean onKeyDown(TextView widget, Spannable buffer,
int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
if (event.getRepeatCount() == 0) {
if (action(CLICK, widget, buffer)) {
return true;
}
}
}
return super.onKeyDown(widget, buffer, keyCode, event);
}
#Override
protected boolean up(TextView widget, Spannable buffer) {
if (action(UP, widget, buffer)) {
return true;
}
return super.up(widget, buffer);
}
#Override
protected boolean down(TextView widget, Spannable buffer) {
if (action(DOWN, widget, buffer)) {
return true;
}
return super.down(widget, buffer);
}
#Override
protected boolean left(TextView widget, Spannable buffer) {
if (action(UP, widget, buffer)) {
return true;
}
return super.left(widget, buffer);
}
#Override
protected boolean right(TextView widget, Spannable buffer) {
if (action(DOWN, widget, buffer)) {
return true;
}
return super.right(widget, buffer);
}
private boolean action(int what, TextView widget, Spannable buffer) {
boolean handled = false;
Layout layout = widget.getLayout();
int padding = widget.getTotalPaddingTop() +
widget.getTotalPaddingBottom();
int areatop = widget.getScrollY();
int areabot = areatop + widget.getHeight() - padding;
int linetop = layout.getLineForVertical(areatop);
int linebot = layout.getLineForVertical(areabot);
int first = layout.getLineStart(linetop);
int last = layout.getLineEnd(linebot);
ClickableSpan[] candidates = buffer.getSpans(first, last, ClickableSpan.class);
int a = Selection.getSelectionStart(buffer);
int b = Selection.getSelectionEnd(buffer);
int selStart = Math.min(a, b);
int selEnd = Math.max(a, b);
if (selStart < 0) {
if (buffer.getSpanStart(FROM_BELOW) >= 0) {
selStart = selEnd = buffer.length();
}
}
if (selStart > last)
selStart = selEnd = Integer.MAX_VALUE;
if (selEnd < first)
selStart = selEnd = -1;
switch (what) {
case CLICK:
if (selStart == selEnd) {
return false;
}
ClickableSpan[] link = buffer.getSpans(selStart, selEnd, ClickableSpan.class);
if (link.length != 1)
return false;
link[0].onClick(widget);
break;
case UP:
int beststart, bestend;
beststart = -1;
bestend = -1;
for (int i = 0; i < candidates.length; i++) {
int end = buffer.getSpanEnd(candidates[i]);
if (end < selEnd || selStart == selEnd) {
if (end > bestend) {
beststart = buffer.getSpanStart(candidates[i]);
bestend = end;
}
}
}
if (beststart >= 0) {
Selection.setSelection(buffer, bestend, beststart);
return true;
}
break;
case DOWN:
beststart = Integer.MAX_VALUE;
bestend = Integer.MAX_VALUE;
for (int i = 0; i < candidates.length; i++) {
int start = buffer.getSpanStart(candidates[i]);
if (start > selStart || selStart == selEnd) {
if (start < beststart) {
beststart = start;
bestend = buffer.getSpanEnd(candidates[i]);
}
}
}
if (bestend < Integer.MAX_VALUE) {
Selection.setSelection(buffer, beststart, bestend);
return true;
}
break;
}
return false;
}
public boolean onKeyUp(TextView widget, Spannable buffer,
int keyCode, KeyEvent event) {
return false;
}
#Override
public boolean onTouchEvent(TextView widget, Spannable buffer,
MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}
return true;
} else {
Selection.removeSelection(buffer);
if (action == MotionEvent.ACTION_UP) {
if(listener != null)
listener.onTextClicked();
}
}
}
return super.onTouchEvent(widget, buffer, event);
}
public void initialize(TextView widget, Spannable text) {
Selection.removeSelection(text);
text.removeSpan(FROM_BELOW);
}
public void onTakeFocus(TextView view, Spannable text, int dir) {
Selection.removeSelection(text);
if ((dir & View.FOCUS_BACKWARD) != 0) {
text.setSpan(FROM_BELOW, 0, 0, Spannable.SPAN_POINT_POINT);
} else {
text.removeSpan(FROM_BELOW);
}
}
public static MovementMethod getInstance() {
if (sInstance == null)
sInstance = new CustomLinkMovementMethod();
return sInstance;
}
private static CustomLinkMovementMethod sInstance;
private static Object FROM_BELOW = new NoCopySpan.Concrete();
}
Then in your code where the text view is add:
CustomLinkMovementMethod link = (CustomLinkMovementMethod)CustomLinkMovementMethod.getInstance();
link.setOnTextClickListener(new CustomLinkMovementMethod.TextClickedListener() {
#Override
public void onTextClicked() {
Toast.makeText(UserProfileActivity.this, "text Pressed", Toast.LENGTH_LONG).show();
}
});
YOUR_TEXTVIEW.setMovementMethod(link);
It's quite simple, you can cancell textview's pending intent about click in ClickableSpan callback
span.setSpan(new ClickableSpan() {
#Override
public void onClick(View v) {
tv.cancelPendingInputEvents() //here new line, textview will not receive click event
Log.d("main", "link clicked");
Toast.makeText(Main.this, "link clicked", Toast.LENGTH_SHORT).show();
} }, 5, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(span);
I think that this involves subclassing TextView and changing its behavior, unfortunately. Have you thought about trying to put a background behind the TextView and attaching an onClickListener to it?
copy below function
private fun setClickableHighLightedText(
tv: TextView,
textToHighlight: String,
onClickListener: View.OnClickListener?
) {
val tvt = tv.text.toString()
var ofe = tvt.indexOf(textToHighlight, 0)
val clickableSpan = object : ClickableSpan() {
override fun onClick(textView: View) {
onClickListener?.onClick(textView)
}
override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds)
//set color of the text
ds.color = getColor(R.color.black)
//draw underline base on true/false
ds.isUnderlineText = false
}
}
val wordToSpan = SpannableString(tv.text)
var ofs = 0
while (ofs < tvt.length && ofe != -1) {
ofe = tvt.indexOf(textToHighlight, ofs)
if (ofe == -1)
break
else {
wordToSpan.setSpan(
clickableSpan,
ofe,
ofe + textToHighlight.length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
tv.setText(wordToSpan, TextView.BufferType.SPANNABLE)
tv.movementMethod = LinkMovementMethod.getInstance()
}
ofs = ofe + 1
}
}
use above function and
pass textview,clickble string
setClickableHighLightedText(tvTest,"test") {
showMessage("click")
}

Android: Trouble with using multiple context menu's

What I have here real simple activity with two buttons. When you press each of them it plays a sound.
When i press and hold the first button it brings up a context menu asking the user if they want to save the sound as a ringtone or notification. This works perfectly on the first button.
The second button's sound plays when pressed. When long pressed it brings up the context menu....BUT it saves the first sound file as ringtone/notification NOT the second...
Would someone be able to shed some insight on why the second context menu isn't working properly?
package com.my.app;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;import android.view.ContextMenu.ContextMenuInfo;
import android.widget.Button;
import android.widget.Toast;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
public class One extends Activity implements OnClickListener{
private SoundManager mSoundManager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.one);
mSoundManager = new SoundManager();
mSoundManager.initSounds(getBaseContext());
mSoundManager.addSound(1, R.raw.blah);
mSoundManager.addSound(2, R.raw.rofl);
//BUTTONS PLAY SOUND WHEN PRESSED
View SoundButton1 = findViewById(R.id.Sound1);
SoundButton1.setOnClickListener(this);
View SoundButton2 = findViewById(R.id.Sound2);
SoundButton2.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.Sound1:
mSoundManager.playSound(1);
break;
case R.id.Sound2:
mSoundManager.playSound(2);
break;
}
//WHEN LONG PRESSED BUTTONS BRING UP CONTEXT MENU FOR SAVE AS RINGTONE OR NOTIFICATION
Button SoundButton11 = (Button) findViewById(R.id.Sound1);
registerForContextMenu(SoundButton11);
Button SoundButton22 = (Button) findViewById(R.id.Sound2);
registerForContextMenu(SoundButton22);
}
//CONTEXT MENU FOR BUTTON 1
#Override
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.setHeaderTitle("Save as...");
menu.add(0, v.getId(), 0, "Ringtone");
menu.add(0, v.getId(), 0, "Notification");
}
#Override
public boolean onContextItemSelected(MenuItem item) {
if(item.getTitle()=="Ringtone"){function1(item.getItemId());}
else if(item.getTitle()=="Notification"){function2(item.getItemId());}
else {return false;}
return true;
}
public void function1(int id){
if (savering(R.raw.blah)){
// Code if successful
Toast.makeText(this, "Saved as Ringtone", Toast.LENGTH_SHORT).show();
}
else
{
// Code if unsuccessful
Toast.makeText(this, "Failed - Check your SDCard", Toast.LENGTH_SHORT).show();
}
}
public void function2(int id){
if (savenot(R.raw.blah)){
// Code if successful
Toast.makeText(this, "Saved as Notification", Toast.LENGTH_SHORT).show();
}
else
{
// Code if unsuccessful
Toast.makeText(this, "Failed - Check your SDCard", Toast.LENGTH_SHORT).show();
}
//CONTEXT MENU FOR BUTTON 2
}
public void onCreateContextMenu1(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.setHeaderTitle("Save as...");
menu.add(0, v.getId(), 0, "Ringtone");
menu.add(0, v.getId(), 0, "Notification");
}
public boolean onContextItemSelected1(MenuItem item) {
if(item.getTitle()=="Ringtone"){function11(item.getItemId());}
else if(item.getTitle()=="Notification"){function21(item.getItemId());}
else {return false;}
return true;
}
public void function11(int id){
if (savering(R.raw.rofl)){
// Code if successful
Toast.makeText(this, "Saved as Ringtone", Toast.LENGTH_SHORT).show();
}
else
{
// Code if unsuccessful
Toast.makeText(this, "Failed - Check your SDCard", Toast.LENGTH_SHORT).show();
}
}
public void function21(int id){
if (savenot(R.raw.rofl)){
// Code if successful
Toast.makeText(this, "Saved as Notification", Toast.LENGTH_SHORT).show();
}
else
{
// Code if unsuccessful
Toast.makeText(this, "Failed - Check your SDCard", Toast.LENGTH_SHORT).show();
}
}
public boolean savering(int ressound){
byte[] buffer=null;
InputStream fIn = getBaseContext().getResources().openRawResource(ressound);
int size=0;
try {
size = fIn.available();
buffer = new byte[size];
fIn.read(buffer);
fIn.close();
} catch (IOException e) {
// TODO Auto-generated catch block
return false;
}
String path="/sdcard/media/audio/ringtones/";
String filename="HahaSound"+".ogg";
boolean exists = (new File(path)).exists();
if (!exists){new File(path).mkdirs();}
FileOutputStream save;
try {
save = new FileOutputStream(path+filename);
save.write(buffer);
save.flush();
save.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
return false;
}
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"+path+filename)));
File k = new File(path, filename);
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "HahaSound");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/ogg");
values.put(MediaStore.Audio.Media.ARTIST, "cssounds ");
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false);
values.put(MediaStore.Audio.Media.IS_ALARM, true);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
//Insert it into the database
this.getContentResolver().insert(MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath()), values);
return true;
}
public boolean savenot(int ressound){
byte[] buffer=null;
InputStream fIn = getBaseContext().getResources().openRawResource(ressound);
int size=0;
try {
size = fIn.available();
buffer = new byte[size];
fIn.read(buffer);
fIn.close();
} catch (IOException e) {
// TODO Auto-generated catch block
return false;
}
String path="/sdcard/media/audio/notifications/";
String filename="HahaSound"+".ogg";
boolean exists = (new File(path)).exists();
if (!exists){new File(path).mkdirs();}
FileOutputStream save;
try {
save = new FileOutputStream(path+filename);
save.write(buffer);
save.flush();
save.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
return false;
}
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"+path+filename)));
File k = new File(path, filename);
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "HahaSoundSound");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/ogg");
values.put(MediaStore.Audio.Media.ARTIST, "cssounds ");
values.put(MediaStore.Audio.Media.IS_RINGTONE, false);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
values.put(MediaStore.Audio.Media.IS_ALARM, true);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
//Insert it into the database
this.getContentResolver().insert(MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath()), values);
return true;
}
}
UPDATED SINCE STOLE'S RESPONSE-
//BUTTON 1
View SoundButton1 = findViewById(R.id.Sound1);
SoundButton1.setOnClickListener(this);
View SoundButton2 = findViewById(R.id.Sound2);
SoundButton2.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.Sound1:
mSoundManager.playSound(1);
break;
case R.id.Sound2:
mSoundManager.playSound(2);
break;
}
Button SoundButton11 = (Button) findViewById(R.id.Sound1);
registerForContextMenu(SoundButton11);
Button SoundButton22 = (Button) findViewById(R.id.Sound2);
registerForContextMenu(SoundButton22);
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.setHeaderTitle("Save as...");
menu.add(0, MENU_RINGTONE, 0, "Ringtone");
menu.add(0, MENU_NOTIFICATION, 0, "Notification");
}
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
long SoundButton11 = info.id;
switch (item.getItemId()) {
case MENU_RINGTONE:
if (savering(R.raw.schwing)){
// Code if successful
Toast.makeText(this, "Saved as Ringtone", Toast.LENGTH_SHORT).show();
}
else
{
// Code if unsuccessful
Toast.makeText(this, "Failed - Check your SDCard", Toast.LENGTH_SHORT).show();
}
break;
case MENU_NOTIFICATION:
if (savenot(R.raw.schwing)){
// Code if successful
Toast.makeText(this, "Saved as Notification", Toast.LENGTH_SHORT).show();
}
else
{
// Code if unsuccessful
Toast.makeText(this, "Failed - Check your SDCard", Toast.LENGTH_SHORT).show();
}
break;
}
return false;
}
This is what 've got since reading your last response. I'm just trying to get it working on the first button before i try moving onto the next. But with your code i'm getting a warning under SoundButton11 "The local variable SoundButton11 is never read"
I'm confused because I have...
Button SoundButton11 = (Button) findViewById(R.id.Sound1);
registerForContextMenu(SoundButton11);
I also tried Sound1 and that did not work either. Any suggestions?
2 Things about your code....
1) There's no function called onCreateContextMenu1 so you're not overriding it...So the first onCreateContextMenu is called.
2)
menu.add(0, v.getId(), 0, "Ringtone");
menu.add(0, v.getId(), 0, "Notification");
You're assigning both menu item (Context) the same id...they ideally have to be different. how else would you identify them. I'm suprised its actually working for you, using titles.
here's what you should be doing...
final int MENU_RINGTONE = 0;
final int MENU_NOTIFICATION = 1;
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, MENU_RINGTONE, 0, "Ringtone");
menu.add(0, MENU_NOTIFICATION, 0, "Notification");
}
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
long buttonId = info.id;
switch (item.getItemId()) {
case MENU_RINGTONE:
function1(buttonId);
break;
case MENU_NOTIFICATION:
function2(buttonId);
break;
}
}
you don't need the additional function12,funtion11,function21,function22...you can generalize them...but i leave that upto you.
Check the comments, i left below...
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
long SoundButton11 = info.id; //THIS IS THE UNUSED VARIABLE!
switch (item.getItemId()) {
case MENU_RINGTONE:
if (savering(R.raw.schwing)){ //this should change based on what button was pressed...
// Code if successful
Toast.makeText(this, "Saved as Ringtone", Toast.LENGTH_SHORT).show();
}
else
{
// Code if unsuccessful
Toast.makeText(this, "Failed - Check your SDCard", Toast.LENGTH_SHORT).show();
}
break;
case MENU_NOTIFICATION:
if (savenot(R.raw.schwing)){ //this should change based on what button was pressed...
// Code if successful
Toast.makeText(this, "Saved as Notification", Toast.LENGTH_SHORT).show();
}
else
{
// Code if unsuccessful
Toast.makeText(this, "Failed - Check your SDCard", Toast.LENGTH_SHORT).show();
}
break;
}
return false;
}
I suppose this is something on the lines that you want...before you do this make sure SoundButton1(& 2) are Instance Variables so they can be accessible in all the functions of your Activity.
//UNTESTED CODE!
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
long SoundButton11 = info.id; //THIS IS THE UNUSED VARIABLE!
int resId = (SoundButton11 == SoundButton1.getId() )? R.raw.schwing : R.raw.rolf;
switch (item.getItemId()) {
case MENU_RINGTONE:
if (savering(resId)){ //use resId instead...
// Code if successful
Toast.makeText(this, "Saved as Ringtone", Toast.LENGTH_SHORT).show();
}
else
.....

Categories

Resources