1cfd74d65d832137e20e193c960802afba73b5d38sm/* 23c1e67e433728684b5f228c5d4f3e5b1457bb271sm * Copyright (C) 2010 The Android Open Source Project 3cfd74d65d832137e20e193c960802afba73b5d38sm * 4cfd74d65d832137e20e193c960802afba73b5d38sm * Licensed under the Apache License, Version 2.0 (the "License"); 5cfd74d65d832137e20e193c960802afba73b5d38sm * you may not use this file except in compliance with the License. 6cfd74d65d832137e20e193c960802afba73b5d38sm * You may obtain a copy of the License at 7cfd74d65d832137e20e193c960802afba73b5d38sm * 8cfd74d65d832137e20e193c960802afba73b5d38sm * http://www.apache.org/licenses/LICENSE-2.0 9cfd74d65d832137e20e193c960802afba73b5d38sm * 10cfd74d65d832137e20e193c960802afba73b5d38sm * Unless required by applicable law or agreed to in writing, software 11cfd74d65d832137e20e193c960802afba73b5d38sm * distributed under the License is distributed on an "AS IS" BASIS, 12cfd74d65d832137e20e193c960802afba73b5d38sm * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cfd74d65d832137e20e193c960802afba73b5d38sm * See the License for the specific language governing permissions and 14cfd74d65d832137e20e193c960802afba73b5d38sm * limitations under the License. 15cfd74d65d832137e20e193c960802afba73b5d38sm */ 16cfd74d65d832137e20e193c960802afba73b5d38sm 17cfd74d65d832137e20e193c960802afba73b5d38smpackage com.replica.replicaisland; 18cfd74d65d832137e20e193c960802afba73b5d38sm 19cfd74d65d832137e20e193c960802afba73b5d38smimport java.util.ArrayList; 20cfd74d65d832137e20e193c960802afba73b5d38sm 21cfd74d65d832137e20e193c960802afba73b5d38smimport android.app.Activity; 22cfd74d65d832137e20e193c960802afba73b5d38smimport android.content.Context; 23cfd74d65d832137e20e193c960802afba73b5d38smimport android.content.Intent; 24cfd74d65d832137e20e193c960802afba73b5d38smimport android.graphics.Canvas; 25cfd74d65d832137e20e193c960802afba73b5d38smimport android.graphics.Paint; 26cfd74d65d832137e20e193c960802afba73b5d38smimport android.graphics.drawable.AnimationDrawable; 27cfd74d65d832137e20e193c960802afba73b5d38smimport android.os.Bundle; 28cfd74d65d832137e20e193c960802afba73b5d38smimport android.os.SystemClock; 29cfd74d65d832137e20e193c960802afba73b5d38smimport android.text.SpannableStringBuilder; 30cfd74d65d832137e20e193c960802afba73b5d38smimport android.text.TextUtils; 31cfd74d65d832137e20e193c960802afba73b5d38smimport android.util.AttributeSet; 32cfd74d65d832137e20e193c960802afba73b5d38smimport android.view.MotionEvent; 33cfd74d65d832137e20e193c960802afba73b5d38smimport android.view.View; 34cfd74d65d832137e20e193c960802afba73b5d38smimport android.widget.ImageView; 35cfd74d65d832137e20e193c960802afba73b5d38smimport android.widget.TextView; 36cfd74d65d832137e20e193c960802afba73b5d38sm 37cfd74d65d832137e20e193c960802afba73b5d38smimport com.replica.replicaisland.ConversationUtils.Conversation; 38cfd74d65d832137e20e193c960802afba73b5d38smimport com.replica.replicaisland.ConversationUtils.ConversationPage; 39cfd74d65d832137e20e193c960802afba73b5d38sm 40cfd74d65d832137e20e193c960802afba73b5d38smpublic class ConversationDialogActivity extends Activity { 41cfd74d65d832137e20e193c960802afba73b5d38sm 42cfd74d65d832137e20e193c960802afba73b5d38sm private final static float TEXT_CHARACTER_DELAY = 0.1f; 43cfd74d65d832137e20e193c960802afba73b5d38sm private final static int TEXT_CHARACTER_DELAY_MS = (int)(TEXT_CHARACTER_DELAY * 1000); 44cfd74d65d832137e20e193c960802afba73b5d38sm private ConversationUtils.Conversation mConversation; 45cfd74d65d832137e20e193c960802afba73b5d38sm private ArrayList<ConversationUtils.ConversationPage> mPages; 46cfd74d65d832137e20e193c960802afba73b5d38sm private int mCurrentPage; 47cfd74d65d832137e20e193c960802afba73b5d38sm 48cfd74d65d832137e20e193c960802afba73b5d38sm private ImageView mOkArrow; 49cfd74d65d832137e20e193c960802afba73b5d38sm private AnimationDrawable mOkAnimation; 50cfd74d65d832137e20e193c960802afba73b5d38sm 51cfd74d65d832137e20e193c960802afba73b5d38sm @Override 52cfd74d65d832137e20e193c960802afba73b5d38sm protected void onCreate(Bundle savedInstanceState) { 53cfd74d65d832137e20e193c960802afba73b5d38sm super.onCreate(savedInstanceState); 54cfd74d65d832137e20e193c960802afba73b5d38sm setContentView(R.layout.conversation_dialog); 55cfd74d65d832137e20e193c960802afba73b5d38sm 56cfd74d65d832137e20e193c960802afba73b5d38sm mOkArrow = (ImageView)findViewById(R.id.ok); 57cfd74d65d832137e20e193c960802afba73b5d38sm mOkArrow.setBackgroundResource(R.anim.ui_button); 58cfd74d65d832137e20e193c960802afba73b5d38sm mOkAnimation = (AnimationDrawable) mOkArrow.getBackground(); 59cfd74d65d832137e20e193c960802afba73b5d38sm mOkArrow.setVisibility(View.INVISIBLE); 60cfd74d65d832137e20e193c960802afba73b5d38sm 61cfd74d65d832137e20e193c960802afba73b5d38sm final Intent callingIntent = getIntent(); 62cfd74d65d832137e20e193c960802afba73b5d38sm final int levelRow = callingIntent.getIntExtra("levelRow", -1); 63cfd74d65d832137e20e193c960802afba73b5d38sm final int levelIndex = callingIntent.getIntExtra("levelIndex", -1); 64cfd74d65d832137e20e193c960802afba73b5d38sm final int index = callingIntent.getIntExtra("index", -1); 65cfd74d65d832137e20e193c960802afba73b5d38sm final int character = callingIntent.getIntExtra("character", 1); 66cfd74d65d832137e20e193c960802afba73b5d38sm 67cfd74d65d832137e20e193c960802afba73b5d38sm mPages = null; 68cfd74d65d832137e20e193c960802afba73b5d38sm 69cfd74d65d832137e20e193c960802afba73b5d38sm // LevelTree.get(mLevelRow, mLevelIndex).dialogResources.character2Entry.get(index) 70cfd74d65d832137e20e193c960802afba73b5d38sm if (levelRow != -1 && levelIndex != -1 && index != -1) { 71cfd74d65d832137e20e193c960802afba73b5d38sm if (character == 1) { 72cfd74d65d832137e20e193c960802afba73b5d38sm mConversation = LevelTree.get(levelRow, levelIndex).dialogResources.character1Conversations.get(index); 73cfd74d65d832137e20e193c960802afba73b5d38sm } else { 74cfd74d65d832137e20e193c960802afba73b5d38sm mConversation = LevelTree.get(levelRow, levelIndex).dialogResources.character2Conversations.get(index); 75cfd74d65d832137e20e193c960802afba73b5d38sm } 76cfd74d65d832137e20e193c960802afba73b5d38sm TypewriterTextView tv = (TypewriterTextView)findViewById(R.id.typewritertext); 77cfd74d65d832137e20e193c960802afba73b5d38sm tv.setParentActivity(this); 78cfd74d65d832137e20e193c960802afba73b5d38sm 79cfd74d65d832137e20e193c960802afba73b5d38sm } else { 80cfd74d65d832137e20e193c960802afba73b5d38sm // bail 81cfd74d65d832137e20e193c960802afba73b5d38sm finish(); 82cfd74d65d832137e20e193c960802afba73b5d38sm } 83cfd74d65d832137e20e193c960802afba73b5d38sm } 84cfd74d65d832137e20e193c960802afba73b5d38sm 85cfd74d65d832137e20e193c960802afba73b5d38sm private void formatPages(Conversation conversation, TextView textView) { 86cfd74d65d832137e20e193c960802afba73b5d38sm Paint paint = new Paint(); 87cfd74d65d832137e20e193c960802afba73b5d38sm final int maxWidth = textView.getWidth(); 88cfd74d65d832137e20e193c960802afba73b5d38sm final int maxHeight = textView.getHeight(); 89cfd74d65d832137e20e193c960802afba73b5d38sm paint.setTextSize(textView.getTextSize()); 90cfd74d65d832137e20e193c960802afba73b5d38sm paint.setTypeface(textView.getTypeface()); 91cfd74d65d832137e20e193c960802afba73b5d38sm 92cfd74d65d832137e20e193c960802afba73b5d38sm for (int page = conversation.pages.size() - 1; page >= 0 ; page--) { 93cfd74d65d832137e20e193c960802afba73b5d38sm ConversationUtils.ConversationPage currentPage = conversation.pages.get(page); 94cfd74d65d832137e20e193c960802afba73b5d38sm CharSequence text = currentPage.text; 95cfd74d65d832137e20e193c960802afba73b5d38sm // Iterate line by line through the text. Add \n if it gets too wide, 96cfd74d65d832137e20e193c960802afba73b5d38sm // and split into a new page if it gets too long. 97cfd74d65d832137e20e193c960802afba73b5d38sm int currentOffset = 0; 98cfd74d65d832137e20e193c960802afba73b5d38sm int textLength = text.length(); 99cfd74d65d832137e20e193c960802afba73b5d38sm SpannableStringBuilder spannedText = new SpannableStringBuilder(text); 100cfd74d65d832137e20e193c960802afba73b5d38sm int lineCount = 0; 101cfd74d65d832137e20e193c960802afba73b5d38sm final float fontHeight = -paint.ascent() + paint.descent(); 102cfd74d65d832137e20e193c960802afba73b5d38sm final int maxLinesPerPage = (int)(maxHeight / fontHeight); 103cfd74d65d832137e20e193c960802afba73b5d38sm CharSequence newline = "\n"; 104cfd74d65d832137e20e193c960802afba73b5d38sm int addedPages = 0; 105cfd74d65d832137e20e193c960802afba73b5d38sm int lastPageStart = 0; 106cfd74d65d832137e20e193c960802afba73b5d38sm do { 107cfd74d65d832137e20e193c960802afba73b5d38sm int fittingChars = paint.breakText(text, currentOffset, textLength, true, maxWidth, null); 108cfd74d65d832137e20e193c960802afba73b5d38sm 109cfd74d65d832137e20e193c960802afba73b5d38sm if (currentOffset + fittingChars < textLength) { 110cfd74d65d832137e20e193c960802afba73b5d38sm fittingChars -= 2; 111cfd74d65d832137e20e193c960802afba73b5d38sm // Text doesn't fit on the line. Insert a return after the last space. 112cfd74d65d832137e20e193c960802afba73b5d38sm int lastSpace = TextUtils.lastIndexOf(text, ' ', currentOffset + fittingChars - 1); 113cfd74d65d832137e20e193c960802afba73b5d38sm if (lastSpace == -1) { 114cfd74d65d832137e20e193c960802afba73b5d38sm // No spaces, just split at the last character. 115cfd74d65d832137e20e193c960802afba73b5d38sm lastSpace = currentOffset + fittingChars - 1; 116cfd74d65d832137e20e193c960802afba73b5d38sm } 117cfd74d65d832137e20e193c960802afba73b5d38sm spannedText.replace(lastSpace, lastSpace + 1, newline, 0, 1); 118cfd74d65d832137e20e193c960802afba73b5d38sm lineCount++; 119cfd74d65d832137e20e193c960802afba73b5d38sm currentOffset = lastSpace + 1; 120cfd74d65d832137e20e193c960802afba73b5d38sm } else { 121cfd74d65d832137e20e193c960802afba73b5d38sm lineCount++; 122cfd74d65d832137e20e193c960802afba73b5d38sm currentOffset = textLength; 123cfd74d65d832137e20e193c960802afba73b5d38sm } 124cfd74d65d832137e20e193c960802afba73b5d38sm 125cfd74d65d832137e20e193c960802afba73b5d38sm if (lineCount >= maxLinesPerPage || currentOffset >= textLength) { 126cfd74d65d832137e20e193c960802afba73b5d38sm lineCount = 0; 127cfd74d65d832137e20e193c960802afba73b5d38sm if (addedPages == 0) { 128cfd74d65d832137e20e193c960802afba73b5d38sm // overwrite the original page 129cfd74d65d832137e20e193c960802afba73b5d38sm currentPage.text = spannedText.subSequence(lastPageStart, currentOffset); 130cfd74d65d832137e20e193c960802afba73b5d38sm } else { 131cfd74d65d832137e20e193c960802afba73b5d38sm // split into a new page 132cfd74d65d832137e20e193c960802afba73b5d38sm ConversationPage newPage = new ConversationPage(); 133cfd74d65d832137e20e193c960802afba73b5d38sm newPage.imageResource = currentPage.imageResource; 134cfd74d65d832137e20e193c960802afba73b5d38sm newPage.text = spannedText.subSequence(lastPageStart, currentOffset); 135cfd74d65d832137e20e193c960802afba73b5d38sm newPage.title = currentPage.title; 136cfd74d65d832137e20e193c960802afba73b5d38sm conversation.pages.add(page + addedPages, newPage); 137cfd74d65d832137e20e193c960802afba73b5d38sm } 138cfd74d65d832137e20e193c960802afba73b5d38sm lastPageStart = currentOffset; 139cfd74d65d832137e20e193c960802afba73b5d38sm addedPages++; 140cfd74d65d832137e20e193c960802afba73b5d38sm } 141cfd74d65d832137e20e193c960802afba73b5d38sm } while (currentOffset < textLength); 142cfd74d65d832137e20e193c960802afba73b5d38sm 143cfd74d65d832137e20e193c960802afba73b5d38sm 144cfd74d65d832137e20e193c960802afba73b5d38sm } 145cfd74d65d832137e20e193c960802afba73b5d38sm 146cfd74d65d832137e20e193c960802afba73b5d38sm // Holy crap we did a lot of allocation there. 147cfd74d65d832137e20e193c960802afba73b5d38sm Runtime.getRuntime().gc(); 148cfd74d65d832137e20e193c960802afba73b5d38sm } 149cfd74d65d832137e20e193c960802afba73b5d38sm 150cfd74d65d832137e20e193c960802afba73b5d38sm @Override 151cfd74d65d832137e20e193c960802afba73b5d38sm public boolean onTouchEvent(MotionEvent event) { 152cfd74d65d832137e20e193c960802afba73b5d38sm if (event.getAction() == MotionEvent.ACTION_UP) { 153cfd74d65d832137e20e193c960802afba73b5d38sm TypewriterTextView tv = (TypewriterTextView)findViewById(R.id.typewritertext); 154cfd74d65d832137e20e193c960802afba73b5d38sm 155cfd74d65d832137e20e193c960802afba73b5d38sm if (tv.getRemainingTime() > 0) { 156cfd74d65d832137e20e193c960802afba73b5d38sm tv.snapToEnd(); 157cfd74d65d832137e20e193c960802afba73b5d38sm } else { 158cfd74d65d832137e20e193c960802afba73b5d38sm mCurrentPage++; 159cfd74d65d832137e20e193c960802afba73b5d38sm if (mCurrentPage < mPages.size()) { 160cfd74d65d832137e20e193c960802afba73b5d38sm showPage(mPages.get(mCurrentPage)); 161cfd74d65d832137e20e193c960802afba73b5d38sm } else { 162cfd74d65d832137e20e193c960802afba73b5d38sm finish(); 163cfd74d65d832137e20e193c960802afba73b5d38sm } 164cfd74d65d832137e20e193c960802afba73b5d38sm } 165cfd74d65d832137e20e193c960802afba73b5d38sm } 166cfd74d65d832137e20e193c960802afba73b5d38sm // Sleep so that the main thread doesn't get flooded with UI events. 167cfd74d65d832137e20e193c960802afba73b5d38sm try { 168cfd74d65d832137e20e193c960802afba73b5d38sm Thread.sleep(32); 169cfd74d65d832137e20e193c960802afba73b5d38sm } catch (InterruptedException e) { 170cfd74d65d832137e20e193c960802afba73b5d38sm // No big deal if this sleep is interrupted. 171cfd74d65d832137e20e193c960802afba73b5d38sm } 172cfd74d65d832137e20e193c960802afba73b5d38sm return true; 173cfd74d65d832137e20e193c960802afba73b5d38sm } 174cfd74d65d832137e20e193c960802afba73b5d38sm 175cfd74d65d832137e20e193c960802afba73b5d38sm protected void showPage(ConversationUtils.ConversationPage page) { 176cfd74d65d832137e20e193c960802afba73b5d38sm TypewriterTextView tv = (TypewriterTextView)findViewById(R.id.typewritertext); 177cfd74d65d832137e20e193c960802afba73b5d38sm tv.setTypewriterText(page.text); 178cfd74d65d832137e20e193c960802afba73b5d38sm 179cfd74d65d832137e20e193c960802afba73b5d38sm mOkArrow.setVisibility(View.INVISIBLE); 180cfd74d65d832137e20e193c960802afba73b5d38sm mOkAnimation.start(); 181cfd74d65d832137e20e193c960802afba73b5d38sm 182cfd74d65d832137e20e193c960802afba73b5d38sm tv.setOkArrow(mOkArrow); 183cfd74d65d832137e20e193c960802afba73b5d38sm 184cfd74d65d832137e20e193c960802afba73b5d38sm ImageView image = (ImageView)findViewById(R.id.speaker); 185cfd74d65d832137e20e193c960802afba73b5d38sm if (page.imageResource != 0) { 186cfd74d65d832137e20e193c960802afba73b5d38sm image.setImageResource(page.imageResource); 187cfd74d65d832137e20e193c960802afba73b5d38sm image.setVisibility(View.VISIBLE); 188cfd74d65d832137e20e193c960802afba73b5d38sm } else { 189cfd74d65d832137e20e193c960802afba73b5d38sm image.setVisibility(View.GONE); 190cfd74d65d832137e20e193c960802afba73b5d38sm } 191cfd74d65d832137e20e193c960802afba73b5d38sm 192cfd74d65d832137e20e193c960802afba73b5d38sm TextView title = (TextView)findViewById(R.id.speakername); 193cfd74d65d832137e20e193c960802afba73b5d38sm if (page.title != null) { 194cfd74d65d832137e20e193c960802afba73b5d38sm title.setText(page.title); 195cfd74d65d832137e20e193c960802afba73b5d38sm title.setVisibility(View.VISIBLE); 196cfd74d65d832137e20e193c960802afba73b5d38sm } else { 197cfd74d65d832137e20e193c960802afba73b5d38sm title.setVisibility(View.GONE); 198cfd74d65d832137e20e193c960802afba73b5d38sm } 199cfd74d65d832137e20e193c960802afba73b5d38sm 200cfd74d65d832137e20e193c960802afba73b5d38sm } 201cfd74d65d832137e20e193c960802afba73b5d38sm 202cfd74d65d832137e20e193c960802afba73b5d38sm public void processText() { 203cfd74d65d832137e20e193c960802afba73b5d38sm if (!mConversation.splittingComplete) { 204cfd74d65d832137e20e193c960802afba73b5d38sm TextView textView = (TextView)findViewById(R.id.typewritertext); 205cfd74d65d832137e20e193c960802afba73b5d38sm formatPages(mConversation, textView); 206cfd74d65d832137e20e193c960802afba73b5d38sm mConversation.splittingComplete = true; 207cfd74d65d832137e20e193c960802afba73b5d38sm } 208cfd74d65d832137e20e193c960802afba73b5d38sm 209cfd74d65d832137e20e193c960802afba73b5d38sm if (mPages == null) { 210cfd74d65d832137e20e193c960802afba73b5d38sm mPages = mConversation.pages; 211cfd74d65d832137e20e193c960802afba73b5d38sm showPage(mPages.get(0)); 212cfd74d65d832137e20e193c960802afba73b5d38sm 213cfd74d65d832137e20e193c960802afba73b5d38sm mCurrentPage = 0; 214cfd74d65d832137e20e193c960802afba73b5d38sm } 215cfd74d65d832137e20e193c960802afba73b5d38sm } 216cfd74d65d832137e20e193c960802afba73b5d38sm 217cfd74d65d832137e20e193c960802afba73b5d38sm 218cfd74d65d832137e20e193c960802afba73b5d38sm public static class TypewriterTextView extends TextView { 219cfd74d65d832137e20e193c960802afba73b5d38sm private int mCurrentCharacter; 220cfd74d65d832137e20e193c960802afba73b5d38sm private long mLastTime; 221cfd74d65d832137e20e193c960802afba73b5d38sm private CharSequence mText; 222cfd74d65d832137e20e193c960802afba73b5d38sm private View mOkArrow; 223cfd74d65d832137e20e193c960802afba73b5d38sm private ConversationDialogActivity mParentActivity; // This really sucks. 224cfd74d65d832137e20e193c960802afba73b5d38sm 225cfd74d65d832137e20e193c960802afba73b5d38sm public TypewriterTextView(Context context) { 226cfd74d65d832137e20e193c960802afba73b5d38sm super(context); 227cfd74d65d832137e20e193c960802afba73b5d38sm } 228cfd74d65d832137e20e193c960802afba73b5d38sm 229cfd74d65d832137e20e193c960802afba73b5d38sm public TypewriterTextView(Context context, AttributeSet attrs) { 230cfd74d65d832137e20e193c960802afba73b5d38sm super(context, attrs); 231cfd74d65d832137e20e193c960802afba73b5d38sm } 232cfd74d65d832137e20e193c960802afba73b5d38sm 233cfd74d65d832137e20e193c960802afba73b5d38sm public TypewriterTextView(Context context, AttributeSet attrs, int defStyle) { 234cfd74d65d832137e20e193c960802afba73b5d38sm super(context, attrs, defStyle); 235cfd74d65d832137e20e193c960802afba73b5d38sm } 236cfd74d65d832137e20e193c960802afba73b5d38sm 237cfd74d65d832137e20e193c960802afba73b5d38sm public void setParentActivity(ConversationDialogActivity parent) { 238cfd74d65d832137e20e193c960802afba73b5d38sm mParentActivity = parent; 239cfd74d65d832137e20e193c960802afba73b5d38sm } 240cfd74d65d832137e20e193c960802afba73b5d38sm 241cfd74d65d832137e20e193c960802afba73b5d38sm public void setTypewriterText(CharSequence text) { 242cfd74d65d832137e20e193c960802afba73b5d38sm mText = text; 243cfd74d65d832137e20e193c960802afba73b5d38sm mCurrentCharacter = 0; 244cfd74d65d832137e20e193c960802afba73b5d38sm mLastTime = 0; 245cfd74d65d832137e20e193c960802afba73b5d38sm postInvalidate(); 246cfd74d65d832137e20e193c960802afba73b5d38sm } 247cfd74d65d832137e20e193c960802afba73b5d38sm 248cfd74d65d832137e20e193c960802afba73b5d38sm public long getRemainingTime() { 249cfd74d65d832137e20e193c960802afba73b5d38sm return (mText.length() - mCurrentCharacter) * TEXT_CHARACTER_DELAY_MS; 250cfd74d65d832137e20e193c960802afba73b5d38sm } 251cfd74d65d832137e20e193c960802afba73b5d38sm 252cfd74d65d832137e20e193c960802afba73b5d38sm public void snapToEnd() { 253cfd74d65d832137e20e193c960802afba73b5d38sm mCurrentCharacter = mText.length() - 1; 254cfd74d65d832137e20e193c960802afba73b5d38sm } 255cfd74d65d832137e20e193c960802afba73b5d38sm 256cfd74d65d832137e20e193c960802afba73b5d38sm public void setOkArrow(View arrow) { 257cfd74d65d832137e20e193c960802afba73b5d38sm mOkArrow = arrow; 258cfd74d65d832137e20e193c960802afba73b5d38sm } 259cfd74d65d832137e20e193c960802afba73b5d38sm 260cfd74d65d832137e20e193c960802afba73b5d38sm 261cfd74d65d832137e20e193c960802afba73b5d38sm @Override 262cfd74d65d832137e20e193c960802afba73b5d38sm protected void onSizeChanged(int w, int h, int oldw, int oldh) { 263cfd74d65d832137e20e193c960802afba73b5d38sm // We need to wait until layout has occurred before we can setup the 264cfd74d65d832137e20e193c960802afba73b5d38sm // text page. Ugh. Bidirectional dependency! 265cfd74d65d832137e20e193c960802afba73b5d38sm if (mParentActivity != null) { 266cfd74d65d832137e20e193c960802afba73b5d38sm mParentActivity.processText(); 267cfd74d65d832137e20e193c960802afba73b5d38sm } 268cfd74d65d832137e20e193c960802afba73b5d38sm super.onSizeChanged(w, h, oldw, oldh); 269cfd74d65d832137e20e193c960802afba73b5d38sm } 270cfd74d65d832137e20e193c960802afba73b5d38sm 271cfd74d65d832137e20e193c960802afba73b5d38sm @Override 272cfd74d65d832137e20e193c960802afba73b5d38sm public void onDraw(Canvas canvas) { 273cfd74d65d832137e20e193c960802afba73b5d38sm final long time = SystemClock.uptimeMillis(); 274cfd74d65d832137e20e193c960802afba73b5d38sm final long delta = time - mLastTime; 275cfd74d65d832137e20e193c960802afba73b5d38sm if (delta > TEXT_CHARACTER_DELAY_MS) { 276cfd74d65d832137e20e193c960802afba73b5d38sm if (mText != null) { 277cfd74d65d832137e20e193c960802afba73b5d38sm if (mCurrentCharacter <= mText.length()) { 278cfd74d65d832137e20e193c960802afba73b5d38sm CharSequence subtext = mText.subSequence(0, mCurrentCharacter); 279cfd74d65d832137e20e193c960802afba73b5d38sm setText(subtext, TextView.BufferType.SPANNABLE); 280cfd74d65d832137e20e193c960802afba73b5d38sm mCurrentCharacter++; 281cfd74d65d832137e20e193c960802afba73b5d38sm postInvalidateDelayed(TEXT_CHARACTER_DELAY_MS); 282cfd74d65d832137e20e193c960802afba73b5d38sm } else { 283cfd74d65d832137e20e193c960802afba73b5d38sm if (mOkArrow != null) { 284cfd74d65d832137e20e193c960802afba73b5d38sm mOkArrow.setVisibility(View.VISIBLE); 285cfd74d65d832137e20e193c960802afba73b5d38sm } 286cfd74d65d832137e20e193c960802afba73b5d38sm } 287cfd74d65d832137e20e193c960802afba73b5d38sm } 288cfd74d65d832137e20e193c960802afba73b5d38sm } 289cfd74d65d832137e20e193c960802afba73b5d38sm super.onDraw(canvas); 290cfd74d65d832137e20e193c960802afba73b5d38sm } 291cfd74d65d832137e20e193c960802afba73b5d38sm } 292cfd74d65d832137e20e193c960802afba73b5d38sm 293cfd74d65d832137e20e193c960802afba73b5d38sm 294cfd74d65d832137e20e193c960802afba73b5d38sm 295cfd74d65d832137e20e193c960802afba73b5d38sm} 296