We can use a TextViewfor adding hyperlinks to it by various methods, like using the attribute autoLink, or by using setMovementMethod().
Can we do the same using and EditText widget? I am trying to create a notepad, in which if any such text entered, like url, email, number or something similar, we should get a hyperlink to click on it and open the browser.
Please help.
Thanks All.
As of Android API level 8 there is a WEB_URL pattern. Quoting the source, it "match[es] most part of RFC 3987". If you target a lower API level you could simply copy the pattern from the source and include it in your application. I assume you know how to use patterns and matchers, so I'm not going into more details here.
Also the class URLUtil provides some useful methods, e.g:
isHttpUrl()
isValidUrl()
The descriptions of the methods are not very elaborate, therefore you are probably best of looking at the source and figuring out which one fits your purpose best.
As for when to trigger the validation check, there are multiple possibilities: you could use the EditText callback functions
onFocusChanged(), or
onTextChanged()
or use a TextWatcher, which I think would be better.
I hope this helps, best regards,
Related
I am working on Android SoftKeyboard. I've created layout for keyboard but dont't know how to include suggestions which appears if we type some word in EditText.
For example if i write "Kn" then "Known" and "Known" are shown in Suggestions.
So my questions are -
1) How to include suggestions in Android Softkeyboard?
2) Is there any way to include our own list of suggestions?
Thanx a lot in advance.
I've already checked this and this but not able to find any proper answer. Any help would be appreciated.
EDIT
I want to include suggestions directly above Keyboard as shown in picture below.
You can use the static method UserDictionary.Words.addWord(....): Link
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
// On JellyBean & above, you can provide a shortcut and an explicit Locale
UserDictionary.Words.addWord(this, "MadeUpWord", 10, "Mad", Locale.getDefault());
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) {
UserDictionary.Words.addWord(this, "MadeUpWord", 10, UserDictionary.Words.LOCALE_TYPE_CURRENT);
}
You will need to add this permission to your manifest:
<uses-permission android:name="android.permission.WRITE_USER_DICTIONARY"/>
Added words will appear in Settings > Language & input > Personal dictionary.
If you are implementing your own soft keyboard, I suggest you go through Creating an Input Method. The suggestions are usually shown in the Candidates View. By default, InputMethodService#onCreateCandidatesView() returns null. You should override this method to return your implementation of the suggestions bar.
Here's a sample project that implements the Candidates view: SoftKeyboard.
More info:
Word and phrase suggestions go in the candidates view. Info about how to create & populate it are in the sample project mentioned above.
As far as I know, the selection of what words/phrases to suggest is developer's responsibility. Android does not provide those for you. You will probably need a set of dictionaries - one for each language/locale you plan on supporting. You may also want to maintain a dictionary of user-specified words.
Android's default keyboard uses these: Link
If you download one of these, unpack it and open with a text editor:
dictionary=main:en,locale=en,description=English,date=1402373178,version=47
word=the,f=222,flags=,originalFreq=222
word=to,f=215,flags=,originalFreq=208
word=of,f=214,flags=,originalFreq=214
word=and,f=212,flags=,originalFreq=212
word=in,f=210,flags=,originalFreq=210
.... 165,635 more lines
As apparent, the frequency plays a pivotal role in determining the suitability of a word as a suggestion. You probably don't want to suggest tachometer when the user types ta. You probably do want to suggest take - frequency helps you there.
Autocorrection:
word=id,f=99,flags=,originalFreq=99
shortcut=I'd,f=whitelist
The flags indicate appropriateness:
word=goddamn,f=0,flags=offensive,originalFreq=62
Even if you decide to use these dictionaries, the code to parse them and obtain meaningful suggestions will have to come from you.
Two articles (both by Peter Kankowski) that talk about predictive text input & spelling correction:
Using DAWG for predictive text input
Using Ternary DAGs for Spelling Correction
CandidatesView:
The first thing you should know about the CandidatesView: it is optional. In fact, LatinIME (android's default soft keyboard) does not use it. Instead LatinIME has its own implementation - SuggestionStripView - which is similar. The default behavior of InputMethodService#onCreateCandidatesView() is to return null. If you choose to provide your own implementation, don't override this method.
You need to decide what your CandidatesView should look like. One possible implementation can be a HorizontalScrollView. After you evaluate your suggestions (for example, user start writing "as", and your suggestion-logic gives you a List<String> containing "has", "was", "assist", "ask", "asked", "asking", "assume"), create & add TextViews holding these strings to the HorizontalScrollView(LinearLayout). This way, user can scroll horizontally and choose the intended word by clicking on it.
It is up to you to decide whether to use the API or handle the CandidatesView yourself. If you want to use the API, override InputMetodService#onCreateCandidatesView(), inflate your custom layout, then return it. Hold a reference to it, so you can update it when required. To control CandidatesView's visibility, use the method setCandidatesViewShown(boolean).
If you are creating a custom keyboard, I suggest you go through Creating Input Method, there is a sample code that you can go over. CandidateView is probably what you are looking for. It is explained in the link above.
If you want to provide inline spell checker, you would want to check out Spellchecker framework
Hope this helps.
I need to make all numbers in a string become links.
The expected action when any of these links is clicked is to append the clicked number to an existing string.
I managed to linkify the numbers by using the following code:
Pattern myMatcher = Pattern.compile("[0-9]*");
Linkify.addLinks(myString, myMatcher, null);
How can I access and retrieve the clicked number in this case?
I tried looking in other questions related to Linkify but seems all are describing ways to have an action that opens an activity or open the default app for that link type (email address/web URL/etc.)
Thanks in advance for you help :)
You can Customize Linkify to append any predefiened string(scheme) into that.
Take a look at the following post Android Developer Blogspot (Search for "Custom Linkify")
For clarity I am describing a portion of that post here:
Linkify will automatically append whatever is matched to a scheme that
is supplied to it, so for the sake of argument let's assume we have a
ContentProvider that matches the following content URI:
content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord
The WikiWord part will be appended by Linkify when it finds a match,
so we just need the part before that as our scheme.
Now that we have these two things, we use Linkify to connect them up:
Pattern wikiWordMatcher = Pattern.compile("\\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\\b");
String wikiViewURL = "content://com.google.android.wikinotes.db.wikinotes/wikinotes/";
Linkify.addLinks(noteView, wikiWordMatcher, wikiViewURL);
Linkify can be used multiple times on the same view to add more links,
so using this after the Default Linkify call means that the existing
active links will be maintained and the new WikiWords will be added.
You could define more Linkify actions and keep applying them to the
same TextView if you wanted to.
Now, if we have a WikiWord in the TextView, let's say MyToDoList,
Linkify will turn it into an active link with the content URI:
content://com.google.android.wikinotes.db.wikinotes/wikinotes/MyToDoList
and if you click on it, Android will fire the default intent for that
content URI.
For this to all work, you will need a ContentProvider that understands
that Content URI, and you will need a default activity capable of
doing something with the resulting data. I plan to cover these in
future blog entries (and soon). In fact, the whole Wiki Note Pad
application is currently undergoing some clean up and review, and will
then hopefully be released as a sample application.
Is there any way to intercept the Android framework's inflation of xml resources (menus and layouts) to change the strings it uses (e.g. for attributes like android:text="#string/button_trade_commit".)
I know it's possible to override getString() as it's called from an Activity. But framework code doesn't seem to use getString(). For example, in MenuInflator.java, strings come from mContext.obtainStyledAttributes(), and obtainStyledAttributes() is final: I can't override it.
Anybody know of another way to accomplish this?
Background: I want to allow non-English-speaking users to localize my app themselves. I imagine an interface that displays the English strings and lets them enter a translation which is then used in place of the English string from then on. I can imagine also providing a "Share translations" button that uploads the translations, and then,
on the server side, incorporating them into a downloadable module that other users of the same language would get. Being able to substitute strings at runtime is the blocking piece that I can't figure out.
I don't believe you can override the systems getString() methods the way you are looking at it.
It might be worth trying to use a custom attribute and handle the work there: http://developer.android.com/training/custom-views/create-view.html#customattr
I don't think you will be able to modify the process Android uses when inflating resources the way you wanted to.
What you can do is to simply not provide any strings (android:text, etc.) in XML files. You can always obtain a reference to any element in your XML file in the code. Once you have a reference, you can provide texts in the code, taking properly localized strings from your custom framework.
I am not sure about this, but i think you can examine the source of Calligraphy library for Android. It is overriding system LayoutInflater to change the FontType, so i imagine you can do the same to change the strings.
I have been creating Spinner controls (Combo boxes/Drop downs) in one of my apps, and was surprised to find out how difficult it was to achieve all of the following features:
User facing Strings are externalized, taking advantage of strings.xml internationalisation (I18N) feature of Android.
Spinner selections operate using a System view, which facilitates not having to work with or map Strings to meaningful values (yuck).
User view to System view mapping should be easy, automated and minimal (i.e not hand rolled for every component).
Others have attempted solutions to this, but universally as far as I could see they suffer from one or many of the following problems:
UI code is creeping into their enum class which doesn’t belong there (messy), nearly all existing solutions suffered from this.
Hardcoded User facing Strings in their enum classes. Because these are not externalized you cannot do I18N using the stock Android features.
Authors typically make the Fragment or Activity an OnItemSelectedListener which perpetuates a common problem of inheritance for convenience, where composition is more appropriate.
I have developed my own solution which does this: http://www.androidanalyse.com/android-spinner-externalize-user-strings-mapped-to-system-enum/
My question is, have I missed something? This seems like something that should not have been this hard (which makes me feel like I'm possibly reinventing the wheel).
Below is some example code showing my solution in-use (which is available Apache 2 license from the link above).
String none = getString(R.string.none);
String light = getString(R.string.light);
String medium = getString(R.string.medium);
String strong = getString(R.string.strong);
SpinnerUtil.createNewSpinner(view, R.id.wind, Arrays.asList(none, light, medium, strong), WindLevel.values(),
new SpinnerItemSelectedListener<WindLevel>() {
public void onItemSelected(Spinner item, WindLevel value) {
// Take whatever action you wish to here.
}});
I would just use ArrayAdapter<WindLevel>. Yes, you created a custom typed listener, but the regular event listener gets the position and can call getItem() on the ArrayAdapter<WindLevel> to get a WindLevel properly typed.
IMHO, the vast majority of Spinner widgets will be populated with material read in from a database, the Internet, or some other dynamic data source, rather than populated by some sort of enum with display values coming from static strings that can be internationalized ahead of time.
This is not to say that your code is useless: if you find it useful, then it was worth writing. And I am sure that there are apps out there that contain your targeted pattern (i.e., a Spinner backed by an enum or equivalent where the display values are known in advance and can be internationalized) who might find your solution useful as well. Every developer who writes enough code cooks up these sorts of helper classes and the like that help map an OS or framework model into something that better fits the developer's own mental model. So long as you are not perceiving any performance issues, it's all good.
Also, note that OnItemSelectedListener is an interface; implementing that interface on an existing class is not inheritance.
I believe the reason nobody answered you is :
What problem are you trying to solve ? Spinners existed prior to your well designed attempt.
Why reinvent them in exactly the same way they exist in Android ?
http://developer.android.com/guide/topics/ui/controls/spinner.html
It is a beautiful wheel indeed you designed, but still, it is just a wheel :)
UPDATE :
I think I begin to understand what you did. This is interesting. I'm not sure why you did not go to the pattern implemented by the ListPreference with its entries and entryvalues.
In fact, I'm not sure I understand why the Android team did not go that route either.
In any case, it is worth proposing your idea to the Android framework. It is after all open source.
The tutorial says to use android.appwidget.action.APPWIDGET_UPDATE in the action element within the XML intent-filter.
However,
this is the value of a String constant ACTION_APPWIDGET_UPDATE in
android.appwidget.AppWidgetManager
-- I am new to Android but in general programming it is encouraged to use symbolic constants rather than literal values.
Can I use android.appwidget.AppWidgetManager.ACTION_APPWIDGET_UPDATE in my xml file rather than "android.appwidget.action.APPWIDGET_UPDATE"?
This is somewhat of a good practices question rather than a get-me-unstuck one.
Please use your custom intent filter action value within res/value/String.xml file and use it in all place where required i.e., manifest.xml as well as other java files.
I think this is the best way i found. Because you have to use changes at only one place and it reflects in every referred places.
Thank you,
The answer is no, Android does not allow it, and I cannot think of a compelling reason why. The question asks specifically about a standard Android string literal, rather than a custom string literal, hence I am not accepting the other answer (which is still a good answer so upvoting).