Samples
Samples
Wiktionary
Language: Oxygene, Platform: Cooper, Category: Android
https://github.com/remobjects/ElementsSamples/tree/master/Oxygene/Cooper/Android/Wiktionary
-
com.example.android.simplewiktionary
-
References
- android
- Source Files
-
Other Files
- res\values\strings.android-xml
- Properties\AndroidManifest.android-xml
- NOTICE
- Readme.txt
- res\anim\slide_in.android-xml
- res\anim\slide_out.android-xml
- res\drawable\app_icon.png
- res\drawable\ic_menu_shuffle.png
- res\drawable\logo_overlay.9.png
- res\drawable\lookup_bg.android-xml
- res\drawable\progress_spin.android-xml
- res\drawable\star_logo.png
- res\drawable\widget_bg.android-xml
- res\drawable\widget_bg_normal.9.png
- res\drawable\widget_bg_pressed.9.png
- res\drawable\widget_bg_selected.9.png
- res\layout\about.layout-xml
- res\layout\lookup.layout-xml
- res\layout\widget_message.layout-xml
- res\layout\widget_word.layout-xml
- res\menu\lookup.android-xml
- res\values\styles.android-xml
- res\values\themes.android-xml
- res\xml\searchable.android-xml
- res\xml\widget_word.android-xml
-
References
LookupActivity.pas
namespace com.example.android.wiktionary;
{*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*}
interface
uses
android.app,
android.content,
android.graphics,
android.net,
android.os,
android.text,
android.text.format,
android.util,
android.view,
android.view.animation,
android.webkit,
android.widget,
java.util;
type
/// <summary>
/// Activity that lets users browse through Wiktionary content. This is just the
/// user interface, and all API communication and parsing is handled in
/// ExtendedWikiHelper.
/// </summary>
LookupActivity = public class(Activity, Animation.AnimationListener)
private
const TAG = 'LookupActivity';
var mTitleBar: View;
var mTitle: TextView;
var mProgress: ProgressBar;
var mWebView: WebView;
var mSlideIn: Animation;
var mSlideOut: Animation;
// History stack of previous words browsed in this session. This is
// referenced when the user taps the "back" key, to possibly intercept and
// show the last-visited entry, instead of closing the activity.
var mHistory: Stack<String> := new Stack<String>;
var mEntryTitle: String;
// Keep track of last time user tapped "back" hard key. When pressed more
// than once within BACK_THRESHOLD, we let the back key fall
// through and close the app.
var mLastPress: Int64 := - 1;
var BACK_THRESHOLD: Int64 := DateUtils.SECOND_IN_MILLIS div 2; readonly;
method startNavigating(aWord: String; pushHistory: Boolean);
protected
method showAbout;
method setEntryTitle(entryText: String);
method setEntryContent(entryContent: String);
public
method onCreate(savedInstanceState: Bundle); override;
method onCreateOptionsMenu(mnu: Menu): Boolean; override;
method onOptionsItemSelected(itm: MenuItem): Boolean; override;
method onKeyDown(keyCode: Integer; &event: KeyEvent): Boolean; override;
method onNewIntent(int: Intent); override;
method onAnimationEnd(animation: Animation);
method onAnimationRepeat(animation: Animation);
method onAnimationStart(animation: Animation);
end;
/// <summary>
/// Background task to handle Wiktionary lookups. This correctly shows and
/// hides the loading animation from the GUI thread before starting a
/// background query to the Wiktionary API. When finished, it transitions
/// back to the GUI thread where it updates with the newly-found entry.
/// </summary>
LookupTask nested in LookupActivity = private class(AsyncTask<String, String, String>)
private
mContext: LookupActivity;
protected
method onPreExecute; override;
method doInBackground(params args: array of String): String; override;
method onProgressUpdate(params args: array of String); override;
method onPostExecute(parsedText: String); override;
public
constructor (aContext: LookupActivity);
end;
implementation
method LookupActivity.onCreate(savedInstanceState: Bundle);
begin
inherited;
ContentView := R.layout.lookup;
// Load animations used to show/hide progress bar
mSlideIn := AnimationUtils.loadAnimation(self, R.anim.slide_in);
mSlideOut := AnimationUtils.loadAnimation(self, R.anim.slide_out);
// Listen for the "in" animation so we make the progress bar visible
// only after the sliding has finished.
mSlideIn.AnimationListener := self;
mTitleBar := findViewById(R.id.title_bar);
mTitle := TextView(findViewById(R.id.title));
mProgress := ProgressBar(findViewById(R.id.progress));
mWebView := WebView(findViewById(R.id.webview));
// Make the view transparent to show background
mWebView.BackgroundColor := 0;//Color.TRANSPARENT;
// Handle incoming intents as possible searches or links
onNewIntent(Intent)
end;
method LookupActivity.onCreateOptionsMenu(mnu: Menu): Boolean;
begin
var inflater := MenuInflater;
inflater.inflate(R.menu.lookup, mnu);
exit true
end;
method LookupActivity.onOptionsItemSelected(itm: MenuItem): Boolean;
begin
case itm.ItemId of
R.id.lookup_search:
begin
onSearchRequested;
exit true
end;
R.id.lookup_random:
begin
startNavigating(nil, true);
exit true
end;
R.id.lookup_about:
begin
showAbout;
exit true
end;
end;
exit false
end;
/// <summary>
/// Intercept the back-key to try walking backwards along our word history
/// stack. If we don't have any remaining history, the key behaves normally
/// and closes this activity.
/// </summary>
/// <param name="keyCode"></param>
/// <param name="event"></param>
/// <returns></returns>
method LookupActivity.onKeyDown(keyCode: Integer; &event: KeyEvent): Boolean;
begin
// Handle back key as long we have a history stack
if (keyCode = KeyEvent.KEYCODE_BACK) and not mHistory.empty then
begin
// Compare against last pressed time, and if user hit multiple times
// in quick succession, we should consider bailing out early.
var currentPress: Int64 := SystemClock.uptimeMillis;
if currentPress - mLastPress < BACK_THRESHOLD then
exit inherited;
mLastPress := currentPress;
// Pop last entry off stack and start loading
var lastEntry: String := mHistory.pop;
startNavigating(lastEntry, false);
exit true
end;
// Otherwise fall through to parent
exit inherited
end;
/// <summary>
/// Start navigating to the given word, pushing any current word onto the
/// history stack if requested. The navigation happens on a background thread
/// and updates the GUI when finished.
/// </summary>
/// <param name="word">The dictionary word to navigate to.</param>
/// <param name="pushHistory">If true, push the current word onto history stack.</param>
method LookupActivity.startNavigating(aWord: String; pushHistory: Boolean);
begin
// Push any current word onto the history stack
if not TextUtils.isEmpty(mEntryTitle) and pushHistory then
mHistory.add(mEntryTitle);
// Start lookup for new word in background
new LookupTask(self).execute(aWord)
end;
/// <summary>
/// Show an about dialog that cites data sources.
/// </summary>
method LookupActivity.showAbout;
begin
// Inflate the about message contents
var messageView: View := LayoutInflater.inflate(R.layout.about, nil, false);
// When linking text, force to always use default color. This works
// around a pressed color state bug.
var txtView: TextView := TextView(messageView.findViewById(R.id.about_credits));
var defaultColor: Integer := txtView.TextColors.DefaultColor;
txtView.TextColor := defaultColor;
var builder: AlertDialog.Builder := new AlertDialog.Builder(self);
builder.Icon := R.drawable.app_icon;
builder.Title := R.string.app_name;
builder.View := messageView;
builder.&create;
builder.show
end;
/// <summary>
/// Because we're singleTop, we handle our own new intents. These usually
/// come from the SearchManager when a search is requested, or from
/// internal links the user clicks on.
/// </summary>
method LookupActivity.onNewIntent(int: Intent);
begin
var action: String := int.Action;
if Intent.ACTION_SEARCH.&equals(action) then
begin
// Start query for incoming search request
var query: String := int.StringExtra[SearchManager.QUERY];
startNavigating(query, true)
end
else
if Intent.ACTION_VIEW.&equals(action) then
begin
// Treat as internal link only if valid Uri and host matches
var data: Uri := int.Data;
if (data <> nil) and ExtendedWikiHelper.WIKI_LOOKUP_HOST.&equals(data.Host) then
begin
var query: String := data.PathSegments.get(0);
startNavigating(query, true)
end
end
else
begin
// If not recognized, then start showing random word
startNavigating(nil, true)
end
end;
/// <summary>
/// Set the title for the current entry.
/// </summary>
method LookupActivity.setEntryTitle(entryText: String);
begin
mEntryTitle := entryText;
mTitle.Text := mEntryTitle
end;
/// <summary>
/// Set the content for the current entry. This will update our
/// WebView to show the requested content.
/// </summary>
method LookupActivity.setEntryContent(entryContent: String);
begin
mWebView.loadDataWithBaseURL(ExtendedWikiHelper.WIKI_AUTHORITY,
entryContent, ExtendedWikiHelper.MIME_TYPE, ExtendedWikiHelper.ENCODING, nil)
end;
method LookupActivity.onAnimationEnd(animation: Animation);
begin
mProgress.Visibility := View.VISIBLE
end;
method LookupActivity.onAnimationRepeat(animation: Animation);
// Not interested if the animation repeats
begin
end;
method LookupActivity.onAnimationStart(animation: Animation);
// Not interested when the animation starts
begin
end;
constructor LookupActivity.LookupTask(aContext: LookupActivity);
begin
inherited constructor;
mContext := aContext
end;
/// <summary>
/// Perform the background query using ExtendedWikiHelper, which
/// may return an error message as the result.
/// </summary>
method LookupActivity.LookupTask.onPreExecute;
begin
mContext.mTitleBar.startAnimation(mContext.mSlideIn)
end;
/// <summary>
/// Our progress update pushes a title bar update.
/// </summary>
method LookupActivity.LookupTask.doInBackground(params args: array of String): String;
begin
var query: String := args[0];
var parsedText: String := nil;
try
// If query word is null, assume request for random word
if query = nil then
query := ExtendedWikiHelper.getRandomWord;
if query <> nil then
begin
// Push our requested word to the title bar
publishProgress(query);
var wikiText: String := ExtendedWikiHelper.getPageContent(query, true);
parsedText := ExtendedWikiHelper.formatWikiText(wikiText)
end;
except
on e: SimpleWikiHelper.ApiException do
Log.e(TAG, 'Problem making wiktionary request', e);
on e: SimpleWikiHelper.ParseException do
Log.e(TAG, 'Problem making wiktionary request', e);
end;
if parsedText = nil then
parsedText := mContext.String[R.string.empty_result];
exit parsedText
end;
/// <summary>
/// When finished, push the newly-found entry content into our
/// WebView and hide the ProgressBar.
/// </summary>
method LookupActivity.LookupTask.onProgressUpdate(params args: array of String);
begin
var searchWord: String := args[0];
mContext.setEntryTitle(searchWord)
end;
method LookupActivity.LookupTask.onPostExecute(parsedText: String);
begin
mContext.mTitleBar.startAnimation(mContext.mSlideOut);
mContext.mProgress.Visibility := View.INVISIBLE;
mContext.setEntryContent(parsedText)
end;
end.
