Ok. These are my problems.
I need to user regular expressions to filet out everything except for letters and then I need to encase the found words within a $word tag.
With this str = str.replaceAll(pattern, "$0");.
right now I am filtering all of the right elements (punctuation, numbers etc) but its encasing every letter within each word in an a tag not the word. so how do I use the regular expression to group the letters to a word?
from "(a tag open)t(a close)(a tag open)h(a close)(a tag open)i(a close)(a tag open)s(a close) (a tag open)i(a close)(a tag open)s(a close) (a tag open)w(a close)(a tag open)r(a close)(a tag open)o(a close)(a tag open)n(a close)(a tag open)g(a close)";
to :
"(a tag open)This(a close) (a tag open)is(a close) (a tag open)right(a close)";
then I'm making them clickable and I need to catch the click event and get the position on screen on the clicked word as I want to use the clicked event to make a tool tip show up just below the clicked word. thank you for your help.
public class MainActivity extends Activity {
public String text = "This is just a sentence to test you. 23 this is another number23!g?";
public TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = explode(text);
tv = (TextView) findViewById(R.id.tv1);
tv.setLinksClickable(true);
tv.setMovementMethod(LinkMovementMethod.getInstance());
Spanned article = Html.fromHtml(text, null, null);
setHTML(article);
}
public void setHTML(Spanned html) {
SpannableString message = new SpannableString(html.toString());
Object[] spans = html.getSpans(0, html.length(), Object.class);
for (Object span : spans) {
int start = html.getSpanStart(span);
int end = html.getSpanEnd(span);
int flags = html.getSpanFlags(span);
if (span instanceof URLSpan) {
URLSpan urlSpan = (URLSpan) span;
span = new CallbackSpan(urlSpan.getURL());
}
message.setSpan(span, start, end, flags);
}
tv.setText(message);
}
public String explode(String str){
String pattern = "([a-zA-Z])";
str = str.replaceAll(pattern, "$0");
return str;
}
private final class CallbackSpan extends ClickableSpan {
private String m_data;
private String url_main;
public CallbackSpan(String url) {
m_data = url.substring(0);
url_main = url;
}
public void onClick(View view) {
TextView item = (TextView)findViewById(R.id.tv2);
item.setText(url_main + " was clicked.");
Log.d("item", url_main);
}
}
}
Latest code ,pls see link form github
message.setSpan(span, start, end, flags);
You need remove origin span before set new span.
Please see below
The onClick() of ClickableSpan is not working for URLSpan?
EDIT
You can capture any span click event by extends LinkMovementMethod
import android.os.Handler;
import android.os.Message;
import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.LinkMovementMethod;
import android.text.method.MovementMethod;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.widget.TextView;
import java.lang.ref.WeakReference;
public class LinkMovementMethodExt extends LinkMovementMethod {
public static final int LinkMovementMethod_Down = 1001;
public static final int LinkMovementMethod_Up = 2002;
private static LinkMovementMethod sInstance;
private Class mSpanClass = null;
private WeakReference<Handler> mWeakReference = null;
public static MovementMethod getInstance(Handler handler, Class spanClass) {
if (sInstance == null) {
sInstance = new LinkMovementMethodExt();
((LinkMovementMethodExt) sInstance).mWeakReference = new WeakReference<>(handler);
((LinkMovementMethodExt) sInstance).mSpanClass = spanClass;
}
return sInstance;
}
#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);
/**
* get you interest span
*/
Object[] spans = buffer.getSpans(off, off, mSpanClass);
if (spans.length != 0) {
if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer, buffer.getSpanStart(spans[0]), buffer.getSpanEnd(spans[0]));
MessageSpan obj = new MessageSpan();
obj.setObj(spans);
obj.setView(widget);
Handler handler = mWeakReference.get();
if (handler != null) {
Message message = handler.obtainMessage();
message.obj = obj;
message.what = LinkMovementMethod_Down;
message.sendToTarget();
return true;
}
return false;
} else if (action == MotionEvent.ACTION_UP) {
Handler handler = mWeakReference.get();
if (handler != null) {
MessageSpan obj = new MessageSpan();
obj.setView(widget);
Message message = handler.obtainMessage();
message.obj = obj;
message.what = LinkMovementMethod_Up;
message.sendToTarget();
return true;
}
return false;
}
}
}
return super.onTouchEvent(widget, buffer, event);
}
public boolean canSelectArbitrarily() {
return true;
}
public boolean onKeyUp(TextView widget, Spannable buffer, int keyCode,
KeyEvent event) {
return false;
}
textView.setMovementMethod(LinkMovementMethodExt.getInstance());
Edit for "android developer"
It is better way to add Handler property for LinkMovementMethodExt class.
You can capture all Spanned which are delivered as Message object.
Snip code in onTouchEvent method:
Message message = Handler.obtainMessage();
message.obj = buffer.getSpans(off, off, Spanned.class);//get all spanned
message.what = 111;//which value ,it is up to you
message.sendToTarget(); //send message to you target handler
You can handler expected spanned in you handler class. May be it is flexible way to handle .
Hope to help you.
Above textview text is <a href='/a'>aaaa</a>123456<a href='/b'>bbbb</b>7890
I understand you requirement : Click 'aaaa',you want get its href value '/a', click 'bbbb',get its href '/b'; Do not trigger default action which is opened in web browser.
If my understand is right, you can do like this:
Set LinkMovementMethod for textview, etc:textview.setMovementMethod(LinkMovementMethodExt.getInstance(handler, URLSpan.class));
Get interest span, here is URLSpan.
In you handler handleMessage method, you can do like this:
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
int what = msg.what;
if (what == 100) {
Object[] spans = (Object[])msg.obj;
for (Object span : spans) {
if (span instanceof URLSpan) {
System.out.println(((URLSpan) span).getURL());
}
}
}
};
};
Download demo code
MainActivity has color property which you can assign which color value as you like.
How to do?
Step1, get current click span.
Step2, set BackgroundColorSpan for current click span
Assuming You want click individual words on the textview?. I din't understand the converts all letters to words in your comment.
The below can be used to click on individual works and it is displayed in a toast.
public class MainActivity extends Activity {
TextView _tv;
String[] each;
SpannableString ss1;
Button b;
EditText et;
String s;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b= (Button) findViewById(R.id.button1);
et = (EditText) findViewById(R.id.ed);
_tv = (TextView) findViewById( R.id.tv );
b.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
s=et.getText().toString();
_tv.setText("");
for(int i=0;i<s.length();i++)
{
each = s.split("\\s+");
}
for(int i=0;i<each.length;i++)
{
System.out.println("................"+each[i]);
ss1= new SpannableString(each[i]);
//StyleSpan boldSpan = new StyleSpan( Typeface.BOLD );
//spannable.setSpan( boldSpan, 41, 52, Spannable.SPAN_INCLUSIVE_INCLUSIVE );
ss1.setSpan(new MyClickableSpan(each[i]), 0, ss1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
_tv.append(ss1);
_tv.append(" ");
}
_tv.setMovementMethod(LinkMovementMethod.getInstance());
}
});
}
class MyClickableSpan extends ClickableSpan{
String clicked;
public MyClickableSpan(String string) {
// TODO Auto-generated constructor stub
clicked =string;
}
//clickable span
public void onClick(View textView) {
//do something
Toast.makeText(MainActivity.this,clicked ,
Toast.LENGTH_SHORT).show();
}
#Override
public void updateDrawState(TextPaint ds) {
ds.setColor(Color.BLACK);//set text color
ds.setUnderlineText(false); // set to false to remove underline
}
}
}
So if a user enters "1234" they will see "1234" in the EditText field. but when that field loses focus I want it to show "****"
So I've implemented a custom TransformationMethod that will only mask the entered text if the EditText field does not have focus.
when I enter the text "12345" it shows it as it should "12345" but when I click on a different field the numbers never get masked. I want to see "*****" but I still see the same "12345"
If I rotate the device though (force it to reload everything) it correctly shows "*****". And when I click on the EditText Field it correctly changes the masked text from "*****" to "12345" So it works when gaining focus but not when losing focus. I've tried implementing an OnFocusChangeListener but it seems to have no affect.
Is there any way I can force the EditText Field to redraw the text when it loses focus?
SetUp:
editText.setTransformationMethod(CustomPasswordTransformationMethod(numUnobfuscatedDigits))
editText.setOnFocusChangeListener { view, hasFocus ->
((EditText)view).invalidate()
((EditText)view).refreshDrawableState()
CustomPasswordTransformationMethod:
public class CustomPasswordTransformationMethod extends PasswordTransformationMethod {
private int unObfuscated = 1;
private boolean mIsFocused = false;
/**
* #param number the number of digits that will be unObfuscated at the end of the input string. Must be a positive integer or 0.
*/
public CustomPasswordTransformationMethod(int number) {
if (number < 0) {
Log.e(TAG, "Invalid parameter number =" + number + " number of un-obfuscated digits must be a positive integer or 0.");
unObfuscated = 0;
}
unObfuscated = number;
}
#Override
public CharSequence getTransformation(CharSequence source, View view) {
return new PasswordCharSequence(source);
}
#Override
public void onFocusChanged(View view, CharSequence sourceText,
boolean focused, int direction,
Rect previouslyFocusedRect) {
super.onFocusChanged(view,sourceText,focused, direction, previouslyFocusedRect);
mIsFocused = focused;
}
private class PasswordCharSequence implements CharSequence {
private CharSequence mSource;
public PasswordCharSequence(CharSequence source) {
mSource = source; // Store char sequence
}
public char charAt(int index) {
if(mIsFocused) return mSource.charAt(index);
else {
if (index < ((length()) - unObfuscated)) return '●';
return mSource.charAt(index);
}
}
public int length() {
return mSource.length(); // Return default
}
public CharSequence subSequence(int start, int end) {
return mSource.subSequence(start, end); // Return default
}
}
};
Try this and see if it does what you need.
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean hasFocus) {
if(hasFocus){
editText.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
}
else{
editText.setTransformationMethod(PasswordTransformationMethod.getInstance());
}
}
});
Maybe you can try to keep it simple:
String password = "";
editText.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean hasFocus) {
if (hasFocus) {
editText.setText(password, TextView.BufferType.EDITABLE);
} else {
password = editText.getText().toString();
String ofuscated = "";
for (int i = 0; i < password.length(); i++){ ofuscated += "*"; }
editText.setText(ofuscated, TextView.BufferType.EDITABLE);
}
}
});
For some EditText views I want to use a custom keyboard instead of the soft one.
The problem is when I click on an EditText for the first time both keyboards are shown. When I click for the second time - the soft keyboard finally disappeares.
What might be the reason for such behavior?
Here's the code I use:
package pkleczek.profiwan.keyboards;
import android.app.Activity;
import android.inputmethodservice.KeyboardView;
import android.text.InputType;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
public abstract class CustomKeyboard {
/** A link to the KeyboardView that is used to render this CustomKeyboard. */
protected KeyboardView mKeyboardView;
/** A link to the activity that hosts the {#link #mKeyboardView}. */
protected Activity mHostActivity;
/** Returns whether the CustomKeyboard is visible. */
public boolean isCustomKeyboardVisible() {
return mKeyboardView.getVisibility() == View.VISIBLE;
}
/**
* Make the CustomKeyboard visible, and hide the system keyboard for view v.
*/
public void showCustomKeyboard(View v) {
mKeyboardView.setVisibility(View.VISIBLE);
mKeyboardView.setEnabled(true);
if (v != null) {
InputMethodManager inputManager = (InputMethodManager) mHostActivity
.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
/** Make the CustomKeyboard invisible. */
public void hideCustomKeyboard() {
mKeyboardView.setVisibility(View.GONE);
mKeyboardView.setEnabled(false);
}
/**
* Register <var>EditText<var> with resource id <var>resid</var> (on the
* hosting activity) for using this custom keyboard.
*
* #param resid
* The resource id of the EditText that registers to the custom
* keyboard.
*/
public void registerEditText(int resid) {
EditText edittext = (EditText) mHostActivity.findViewById(resid);
edittext.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
showCustomKeyboard(v);
} else {
hideCustomKeyboard();
}
}
});
edittext.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
showCustomKeyboard(v);
}
});
edittext.setInputType(edittext.getInputType()
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
}
}
Try to put the following condition in your InputMethodManager code before inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);line:
if (inputManager!=null) {
Activity activity = getActivity();
if (acvivity == null)
return;
if (activity.getCurrentFocus() == null)
return;
if (activity.getCurrentFocus().getWindowToken() == null)
return;
inputManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}
I used it in ListFragment to hide the default keyboard. First when i press an EditText and keyboard is shown and when on onScrollStateChanged i hide it.
You can also try to put the InputMethodManager code inside the onClickListener of the EditText and then call your showCustomKeyboard() method.
Put an Else statement and Log in it after the if (v != null), maybe your View v is null.
The solution provided by Rotemmiz in the topic Close/hide the Android Soft Keyboard worked for me.
An abstract:
public void setEditTextFocus(EditText editText, boolean isFocused)
{
editText.setCursorVisible(isFocused);
editText.setFocusable(isFocused);
editText.setFocusableInTouchMode(isFocused);
if (isFocused)
{
editText.requestFocus();
}
}
I have a SpannableString with a ClickableSpan as follows
for (int i = 0; i < items.size(); i++) {
final SpannableString span = new SpannableString(items.get(i));
final int index=i;
span.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
}
#Override
public void updateDrawState(TextPaint ds) {
ds.setColor(Color.LTGRAY);
ds.setUnderlineText(false);
}
}, 0, span.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.append(span);
}
//my text view
txt.setText(builder);
txt.setMovementMethod(LinkMovementMethod.getInstance());
what I want to do is to change the foreground color of the span when clicked.
how can I do this ?
If you're looking to get rid of the green highlight on selection, this is what you want to know:
Apparently, overriding public void updateDrawState(TextPaint ds) in your custom class would not affect the highlight color. It is only used for setting the underline color (or hiding/showing it).
All you need to do is:
textView.setHighlightColor(Color.TRANSPARENT);
where textView is what contains the ClickableSpan.
Hope it works for all of you.
Feel free to ask any related question.
I extended the clickableSpan class and passed it a flag that lets me know that I should highlight it.
SpannableStringBuilder tag;
.... tag.setSpan(new WordSpan(i, tokens[i], wordtohighlitedID) {
.....
import android.graphics.Color;
import android.text.TextPaint;
import android.text.style.ClickableSpan;
import android.view.View;
public class WordSpan extends ClickableSpan
{
private int id;
private TextPaint textpaint;
public boolean shouldHilightWord = false;
public WordSpan(int anID, String txt, int selected) {
id =anID;
// if the word selected is the same as the ID set the highlight flag
if(selected == id) {
shouldHilightWord = true;
}
}
#Override
public void updateDrawState(TextPaint ds) {
textpaint = ds;
ds.setColor(ds.linkColor);
if(shouldHilightWord){
textpaint.bgColor = Color.GRAY;
textpaint.setARGB(255, 255, 255, 255);
}
//Remove default underline associated with spans
ds.setUnderlineText(false);
}
public void changeSpanBgColor(View widget){
shouldHilightWord = true;
updateDrawState(textpaint);
widget.invalidate();
}
#Override
public void onClick(View widget) {
// TODO Auto-generated method stub
}
/**
* This function sets the span to record the word number, as the span ID
* #param spanID
*/
public void setSpanTextID(int spanID){
id = spanID;
}
/**
* Return the wordId of this span
* #return id
*/
public int getSpanTextID(){
return id;
}
}
Use this:
view.setSelector(new ColorDrawable(Color.BLUE));
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I would like to play around with some ideas and develop a soft keyboard for Android to replace the default one.
Is there any general information about soft keyboard development for Android out there? Any best practices or guidelines?
Can I do with my keyboard application pretty much anything I could do with a normal Android application?
Can I do HTTP connections to synchronize keyboard data with a cloud DB and other phones I have?
Can I open other windows/screens from a key press, e.g. to display a custom input interface different to a normal QWERTY one. If that doesn't work, can I use a pop-up dialog instead?
Some tips:
Read this tutorial: Creating an Input Method
clone this repo: LatinIME
About your questions:
An inputMethod is basically an Android Service, so yes, you can do HTTP and all the stuff you can do in a Service.
You can open Activities and dialogs from the InputMethod. Once again, it's just a Service.
I've been developing an IME, so ask again if you run into an issue.
Create Custom Key Board for Own EditText
Download Entire Code
In this post i Created Simple Keyboard which contains Some special keys like
( France keys ) and it's supported Capital letters and small letters and Number keys
and some Symbols .
package sra.keyboard;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
public class Main extends Activity implements OnTouchListener, OnClickListener,
OnFocusChangeListener {
private EditText mEt, mEt1; // Edit Text boxes
private Button mBSpace, mBdone, mBack, mBChange, mNum;
private RelativeLayout mLayout, mKLayout;
private boolean isEdit = false, isEdit1 = false;
private String mUpper = "upper", mLower = "lower";
private int w, mWindowWidth;
private String sL[] = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
"k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
"x", "y", "z", "ç", "à", "é", "è", "û", "î" };
private String cL[] = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W",
"X", "Y", "Z", "ç", "à", "é", "è", "û", "î" };
private String nS[] = { "!", ")", "'", "#", "3", "$", "%", "&", "8", "*",
"?", "/", "+", "-", "9", "0", "1", "4", "#", "5", "7", "(", "2",
"\"", "6", "_", "=", "]", "[", "<", ">", "|" };
private Button mB[] = new Button[32];
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
setContentView(R.layout.main);
// adjusting key regarding window sizes
setKeys();
setFrow();
setSrow();
setTrow();
setForow();
mEt = (EditText) findViewById(R.id.xEt);
mEt.setOnTouchListener(this);
mEt.setOnFocusChangeListener(this);
mEt1 = (EditText) findViewById(R.id.et1);
mEt1.setOnTouchListener(this);
mEt1.setOnFocusChangeListener(this);
mEt.setOnClickListener(this);
mEt1.setOnClickListener(this);
mLayout = (RelativeLayout) findViewById(R.id.xK1);
mKLayout = (RelativeLayout) findViewById(R.id.xKeyBoard);
} catch (Exception e) {
Log.w(getClass().getName(), e.toString());
}
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (v == mEt) {
hideDefaultKeyboard();
enableKeyboard();
}
if (v == mEt1) {
hideDefaultKeyboard();
enableKeyboard();
}
return true;
}
#Override
public void onClick(View v) {
if (v == mBChange) {
if (mBChange.getTag().equals(mUpper)) {
changeSmallLetters();
changeSmallTags();
} else if (mBChange.getTag().equals(mLower)) {
changeCapitalLetters();
changeCapitalTags();
}
} else if (v != mBdone && v != mBack && v != mBChange && v != mNum) {
addText(v);
} else if (v == mBdone) {
disableKeyboard();
} else if (v == mBack) {
isBack(v);
} else if (v == mNum) {
String nTag = (String) mNum.getTag();
if (nTag.equals("num")) {
changeSyNuLetters();
changeSyNuTags();
mBChange.setVisibility(Button.INVISIBLE);
}
if (nTag.equals("ABC")) {
changeCapitalLetters();
changeCapitalTags();
}
}
}
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (v == mEt && hasFocus == true) {
isEdit = true;
isEdit1 = false;
} else if (v == mEt1 && hasFocus == true) {
isEdit = false;
isEdit1 = true;
}
}
private void addText(View v) {
if (isEdit == true) {
String b = "";
b = (String) v.getTag();
if (b != null) {
// adding text in Edittext
mEt.append(b);
}
}
if (isEdit1 == true) {
String b = "";
b = (String) v.getTag();
if (b != null) {
// adding text in Edittext
mEt1.append(b);
}
}
}
private void isBack(View v) {
if (isEdit == true) {
CharSequence cc = mEt.getText();
if (cc != null && cc.length() > 0) {
{
mEt.setText("");
mEt.append(cc.subSequence(0, cc.length() - 1));
}
}
}
if (isEdit1 == true) {
CharSequence cc = mEt1.getText();
if (cc != null && cc.length() > 0) {
{
mEt1.setText("");
mEt1.append(cc.subSequence(0, cc.length() - 1));
}
}
}
}
private void changeSmallLetters() {
mBChange.setVisibility(Button.VISIBLE);
for (int i = 0; i < sL.length; i++)
mB[i].setText(sL[i]);
mNum.setTag("12#");
}
private void changeSmallTags() {
for (int i = 0; i < sL.length; i++)
mB[i].setTag(sL[i]);
mBChange.setTag("lower");
mNum.setTag("num");
}
private void changeCapitalLetters() {
mBChange.setVisibility(Button.VISIBLE);
for (int i = 0; i < cL.length; i++)
mB[i].setText(cL[i]);
mBChange.setTag("upper");
mNum.setText("12#");
}
private void changeCapitalTags() {
for (int i = 0; i < cL.length; i++)
mB[i].setTag(cL[i]);
mNum.setTag("num");
}
private void changeSyNuLetters() {
for (int i = 0; i < nS.length; i++)
mB[i].setText(nS[i]);
mNum.setText("ABC");
}
private void changeSyNuTags() {
for (int i = 0; i < nS.length; i++)
mB[i].setTag(nS[i]);
mNum.setTag("ABC");
}
// enabling customized keyboard
private void enableKeyboard() {
mLayout.setVisibility(RelativeLayout.VISIBLE);
mKLayout.setVisibility(RelativeLayout.VISIBLE);
}
// Disable customized keyboard
private void disableKeyboard() {
mLayout.setVisibility(RelativeLayout.INVISIBLE);
mKLayout.setVisibility(RelativeLayout.INVISIBLE);
}
private void hideDefaultKeyboard() {
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
}
private void setFrow() {
w = (mWindowWidth / 13);
w = w - 15;
mB[16].setWidth(w);
mB[22].setWidth(w + 3);
mB[4].setWidth(w);
mB[17].setWidth(w);
mB[19].setWidth(w);
mB[24].setWidth(w);
mB[20].setWidth(w);
mB[8].setWidth(w);
mB[14].setWidth(w);
mB[15].setWidth(w);
mB[16].setHeight(50);
mB[22].setHeight(50);
mB[4].setHeight(50);
mB[17].setHeight(50);
mB[19].setHeight(50);
mB[24].setHeight(50);
mB[20].setHeight(50);
mB[8].setHeight(50);
mB[14].setHeight(50);
mB[15].setHeight(50);
}
private void setSrow() {
w = (mWindowWidth / 10);
mB[0].setWidth(w);
mB[18].setWidth(w);
mB[3].setWidth(w);
mB[5].setWidth(w);
mB[6].setWidth(w);
mB[7].setWidth(w);
mB[26].setWidth(w);
mB[9].setWidth(w);
mB[10].setWidth(w);
mB[11].setWidth(w);
mB[26].setWidth(w);
mB[0].setHeight(50);
mB[18].setHeight(50);
mB[3].setHeight(50);
mB[5].setHeight(50);
mB[6].setHeight(50);
mB[7].setHeight(50);
mB[9].setHeight(50);
mB[10].setHeight(50);
mB[11].setHeight(50);
mB[26].setHeight(50);
}
private void setTrow() {
w = (mWindowWidth / 12);
mB[25].setWidth(w);
mB[23].setWidth(w);
mB[2].setWidth(w);
mB[21].setWidth(w);
mB[1].setWidth(w);
mB[13].setWidth(w);
mB[12].setWidth(w);
mB[27].setWidth(w);
mB[28].setWidth(w);
mBack.setWidth(w);
mB[25].setHeight(50);
mB[23].setHeight(50);
mB[2].setHeight(50);
mB[21].setHeight(50);
mB[1].setHeight(50);
mB[13].setHeight(50);
mB[12].setHeight(50);
mB[27].setHeight(50);
mB[28].setHeight(50);
mBack.setHeight(50);
}
private void setForow() {
w = (mWindowWidth / 10);
mBSpace.setWidth(w * 4);
mBSpace.setHeight(50);
mB[29].setWidth(w);
mB[29].setHeight(50);
mB[30].setWidth(w);
mB[30].setHeight(50);
mB[31].setHeight(50);
mB[31].setWidth(w);
mBdone.setWidth(w + (w / 1));
mBdone.setHeight(50);
}
private void setKeys() {
mWindowWidth = getWindowManager().getDefaultDisplay().getWidth(); // getting
// window
// height
// getting ids from xml files
mB[0] = (Button) findViewById(R.id.xA);
mB[1] = (Button) findViewById(R.id.xB);
mB[2] = (Button) findViewById(R.id.xC);
mB[3] = (Button) findViewById(R.id.xD);
mB[4] = (Button) findViewById(R.id.xE);
mB[5] = (Button) findViewById(R.id.xF);
mB[6] = (Button) findViewById(R.id.xG);
mB[7] = (Button) findViewById(R.id.xH);
mB[8] = (Button) findViewById(R.id.xI);
mB[9] = (Button) findViewById(R.id.xJ);
mB[10] = (Button) findViewById(R.id.xK);
mB[11] = (Button) findViewById(R.id.xL);
mB[12] = (Button) findViewById(R.id.xM);
mB[13] = (Button) findViewById(R.id.xN);
mB[14] = (Button) findViewById(R.id.xO);
mB[15] = (Button) findViewById(R.id.xP);
mB[16] = (Button) findViewById(R.id.xQ);
mB[17] = (Button) findViewById(R.id.xR);
mB[18] = (Button) findViewById(R.id.xS);
mB[19] = (Button) findViewById(R.id.xT);
mB[20] = (Button) findViewById(R.id.xU);
mB[21] = (Button) findViewById(R.id.xV);
mB[22] = (Button) findViewById(R.id.xW);
mB[23] = (Button) findViewById(R.id.xX);
mB[24] = (Button) findViewById(R.id.xY);
mB[25] = (Button) findViewById(R.id.xZ);
mB[26] = (Button) findViewById(R.id.xS1);
mB[27] = (Button) findViewById(R.id.xS2);
mB[28] = (Button) findViewById(R.id.xS3);
mB[29] = (Button) findViewById(R.id.xS4);
mB[30] = (Button) findViewById(R.id.xS5);
mB[31] = (Button) findViewById(R.id.xS6);
mBSpace = (Button) findViewById(R.id.xSpace);
mBdone = (Button) findViewById(R.id.xDone);
mBChange = (Button) findViewById(R.id.xChange);
mBack = (Button) findViewById(R.id.xBack);
mNum = (Button) findViewById(R.id.xNum);
for (int i = 0; i < mB.length; i++)
mB[i].setOnClickListener(this);
mBSpace.setOnClickListener(this);
mBdone.setOnClickListener(this);
mBack.setOnClickListener(this);
mBChange.setOnClickListener(this);
mNum.setOnClickListener(this);
}
}
A good place to start is the sample application provided on the developer docs.
Guidelines would be to just make it as usable as possible. Take a look at the others available on the market to see what you should be aiming for
Yes, services can do most things, including internet; provided you have asked for those permissions
You can open activities and do anything you like n those if you run into a problem with doing some things in the keyboard. For example HTC's keyboard has a button to open the settings activity, and another to open a dialog to change languages.
Take a look at other IME's to see what you should be aiming for. Some (like the official one) are open source.
first of all you should define an .xml file and make keyboard UI in it:
<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="12.50%p"
android:keyHeight="7%p">
<!--
android:horizontalGap="0.50%p"
android:verticalGap="0.50%p"
NOTE When we add a horizontalGap in pixels, this interferes with keyWidth in percentages adding up to 100%
NOTE When we have a horizontalGap (on Keyboard level) of 0, this make the horizontalGap (on Key level) to move from after the key to before the key... (I consider this a bug)
-->
<Row>
<Key android:codes="-5" android:keyLabel="remove" android:keyEdgeFlags="left" />
<Key android:codes="48" android:keyLabel="0" />
<Key android:codes="55006" android:keyLabel="clear" />
</Row>
<Row>
<Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left" />
<Key android:codes="50" android:keyLabel="2" />
<Key android:codes="51" android:keyLabel="3" />
</Row>
<Row>
<Key android:codes="52" android:keyLabel="4" android:keyEdgeFlags="left" />
<Key android:codes="53" android:keyLabel="5" />
<Key android:codes="54" android:keyLabel="6" />
</Row>
<Row>
<Key android:codes="55" android:keyLabel="7" android:keyEdgeFlags="left" />
<Key android:codes="56" android:keyLabel="8" />
<Key android:codes="57" android:keyLabel="9" />
</Row>
In this example you have 4 rows and in each row you have 3 keys.
also you can put an icon in each key you want.
Then you should add xml tag in your activity UI like this:
<android.inputmethodservice.KeyboardView
android:id="#+id/keyboardview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/white"
android:focusable="true"
android:focusableInTouchMode="true"
android:visibility="visible" />
Also in your .java activity file you should define the keyboard and assign it to a EditText:
CustomKeyboard mCustomKeyboard1 = new CustomKeyboard(this,
R.id.keyboardview1, R.xml.horizontal_keyboard);
mCustomKeyboard1.registerEditText(R.id.inputSearch);
This code asign inputSearch (which is a EditText) to your keyboard.
import android.app.Activity;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.inputmethodservice.KeyboardView.OnKeyboardActionListener;
import android.text.Editable;
import android.text.InputType;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
public class CustomKeyboard {
/** A link to the KeyboardView that is used to render this CustomKeyboard. */
private KeyboardView mKeyboardView;
/** A link to the activity that hosts the {#link #mKeyboardView}. */
private Activity mHostActivity;
/** The key (code) handler. */
private OnKeyboardActionListener mOnKeyboardActionListener = new OnKeyboardActionListener() {
public final static int CodeDelete = -5; // Keyboard.KEYCODE_DELETE
public final static int CodeCancel = -3; // Keyboard.KEYCODE_CANCEL
public final static int CodePrev = 55000;
public final static int CodeAllLeft = 55001;
public final static int CodeLeft = 55002;
public final static int CodeRight = 55003;
public final static int CodeAllRight = 55004;
public final static int CodeNext = 55005;
public final static int CodeClear = 55006;
#Override
public void onKey(int primaryCode, int[] keyCodes) {
// NOTE We can say '<Key android:codes="49,50" ... >' in the xml
// file; all codes come in keyCodes, the first in this list in
// primaryCode
// Get the EditText and its Editable
View focusCurrent = mHostActivity.getWindow().getCurrentFocus();
if (focusCurrent == null
|| focusCurrent.getClass() != EditText.class)
return;
EditText edittext = (EditText) focusCurrent;
Editable editable = edittext.getText();
int start = edittext.getSelectionStart();
// Apply the key to the edittext
if (primaryCode == CodeCancel) {
hideCustomKeyboard();
} else if (primaryCode == CodeDelete) {
if (editable != null && start > 0)
editable.delete(start - 1, start);
} else if (primaryCode == CodeClear) {
if (editable != null)
editable.clear();
} else if (primaryCode == CodeLeft) {
if (start > 0)
edittext.setSelection(start - 1);
} else if (primaryCode == CodeRight) {
if (start < edittext.length())
edittext.setSelection(start + 1);
} else if (primaryCode == CodeAllLeft) {
edittext.setSelection(0);
} else if (primaryCode == CodeAllRight) {
edittext.setSelection(edittext.length());
} else if (primaryCode == CodePrev) {
View focusNew = edittext.focusSearch(View.FOCUS_BACKWARD);
if (focusNew != null)
focusNew.requestFocus();
} else if (primaryCode == CodeNext) {
View focusNew = edittext.focusSearch(View.FOCUS_FORWARD);
if (focusNew != null)
focusNew.requestFocus();
} else { // insert character
editable.insert(start, Character.toString((char) primaryCode));
}
}
#Override
public void onPress(int arg0) {
}
#Override
public void onRelease(int primaryCode) {
}
#Override
public void onText(CharSequence text) {
}
#Override
public void swipeDown() {
}
#Override
public void swipeLeft() {
}
#Override
public void swipeRight() {
}
#Override
public void swipeUp() {
}
};
/**
* Create a custom keyboard, that uses the KeyboardView (with resource id
* <var>viewid</var>) of the <var>host</var> activity, and load the keyboard
* layout from xml file <var>layoutid</var> (see {#link Keyboard} for
* description). Note that the <var>host</var> activity must have a
* <var>KeyboardView</var> in its layout (typically aligned with the bottom
* of the activity). Note that the keyboard layout xml file may include key
* codes for navigation; see the constants in this class for their values.
* Note that to enable EditText's to use this custom keyboard, call the
* {#link #registerEditText(int)}.
*
* #param host
* The hosting activity.
* #param viewid
* The id of the KeyboardView.
* #param layoutid
* The id of the xml file containing the keyboard layout.
*/
public CustomKeyboard(Activity host, int viewid, int layoutid) {
mHostActivity = host;
mKeyboardView = (KeyboardView) mHostActivity.findViewById(viewid);
mKeyboardView.setKeyboard(new Keyboard(mHostActivity, layoutid));
mKeyboardView.setPreviewEnabled(false); // NOTE Do not show the preview
// balloons
mKeyboardView.setOnKeyboardActionListener(mOnKeyboardActionListener);
// Hide the standard keyboard initially
mHostActivity.getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
}
/** Returns whether the CustomKeyboard is visible. */
public boolean isCustomKeyboardVisible() {
return mKeyboardView.getVisibility() == View.VISIBLE;
}
/**
* Make the CustomKeyboard visible, and hide the system keyboard for view v.
*/
public void showCustomKeyboard(View v) {
mKeyboardView.setVisibility(View.VISIBLE);
mKeyboardView.setEnabled(true);
if (v != null)
((InputMethodManager) mHostActivity
.getSystemService(Activity.INPUT_METHOD_SERVICE))
.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
/** Make the CustomKeyboard invisible. */
public void hideCustomKeyboard() {
mKeyboardView.setVisibility(View.GONE);
mKeyboardView.setEnabled(false);
}
/**
* Register <var>EditText<var> with resource id <var>resid</var> (on the
* hosting activity) for using this custom keyboard.
*
* #param resid
* The resource id of the EditText that registers to the custom
* keyboard.
*/
public void registerEditText(int resid) {
// Find the EditText 'resid'
EditText edittext = (EditText) mHostActivity.findViewById(resid);
// Make the custom keyboard appear
edittext.setOnFocusChangeListener(new OnFocusChangeListener() {
// NOTE By setting the on focus listener, we can show the custom
// keyboard when the edit box gets focus, but also hide it when the
// edit box loses focus
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus)
showCustomKeyboard(v);
else
hideCustomKeyboard();
}
});
edittext.setOnClickListener(new OnClickListener() {
// NOTE By setting the on click listener, we can show the custom
// keyboard again, by tapping on an edit box that already had focus
// (but that had the keyboard hidden).
#Override
public void onClick(View v) {
showCustomKeyboard(v);
}
});
// Disable standard keyboard hard way
// NOTE There is also an easy way:
// 'edittext.setInputType(InputType.TYPE_NULL)' (but you will not have a
// cursor, and no 'edittext.setCursorVisible(true)' doesn't work )
edittext.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
EditText edittext = (EditText) v;
int inType = edittext.getInputType(); // Backup the input type
edittext.setInputType(InputType.TYPE_NULL); // Disable standard
// keyboard
edittext.onTouchEvent(event); // Call native handler
edittext.setInputType(inType); // Restore input type
return true; // Consume touch event
}
});
// Disable spell check (hex strings look like words to Android)
edittext.setInputType(edittext.getInputType()
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
}
}
// NOTE How can we change the background color of some keys (like the
// shift/ctrl/alt)?
// NOTE What does android:keyEdgeFlags do/mean