Created
September 20, 2012 07:23
-
-
Save gokhanbarisaker/3754407 to your computer and use it in GitHub Desktop.
characters with navigation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static String generateCharacterTagByIndex(int index) | |
{ | |
return (Integer.toString(index + 14970)); | |
} | |
class NavigatableEditText extends EditText | |
{ | |
private WeakReference<View> navigationNext = null; | |
private WeakReference<View> navigationPrevious = null; | |
public NavigatableEditText(Context context) | |
{ | |
super(context); | |
// TODO Auto-generated constructor stub | |
} | |
/** | |
* @return the navigationNext | |
*/ | |
public View getNavigationNext() | |
{ | |
return (navigationNext == null)?(null):(navigationNext.get()); | |
} | |
/** | |
* @param navigationNext the navigationNext to set | |
*/ | |
public void setNavigationNext(View navigationNext) | |
{ | |
this.navigationNext = new WeakReference<View>(navigationNext); | |
} | |
/** | |
* @return the navigationPrevious | |
*/ | |
public View getNavigationPrevious() | |
{ | |
return (navigationPrevious == null)?(null):(navigationPrevious.get()); | |
} | |
/** | |
* @param navigationPrevious the navigationPrevious to set | |
*/ | |
public void setNavigationPrevious(View navigationPrevious) | |
{ | |
this.navigationPrevious = new WeakReference<View>(navigationPrevious); | |
} | |
} | |
class CharacterBox extends NavigatableEditText | |
{ | |
/************************************************* | |
* Log | |
*/ | |
private static final String TAG = "Character Box"; | |
private static final boolean LOG = true; | |
private CharacterState state; | |
public CharacterBox(Context context) | |
{ | |
super(context); | |
setText(""); | |
setState(CharacterState.STATE_INVISIBLE); | |
updateBackground(false); | |
super.setOnFocusChangeListener(new CharacterBoxOnFocusChangeListener()); | |
super.setOnKeyListener(new CharacterBoxOnKeyListener()); | |
super.addTextChangedListener(new CharacterBoxTextWatcher(this)); | |
super.setFilters(new InputFilter[]{ new InputFilter.LengthFilter(99) }); | |
} | |
public CharacterState getState() { | |
return state; | |
} | |
public void setState(CharacterState state) { | |
this.state = state; | |
} | |
// @Override | |
// public void setOnFocusChangeListener(OnFocusChangeListener l) | |
// { | |
// super.setOnFocusChangeListener(l); | |
// | |
// Exception deprecatedMethodException = new Exception("Attaching View.OnFocusChageListener() is deprecated."); | |
// | |
// throw deprecatedMethodException; | |
// } | |
public void moveToNextCharacter() | |
{ | |
CharacterBox nextCharacterBox = (CharacterBox) getNavigationNext(); | |
// If no view defined for next | |
if(nextCharacterBox == null) | |
{ | |
if(LOG) | |
{ | |
Log.d(TAG, "No navigationNext defined for CharacterBox with tag: " + getTag()); | |
} | |
// Clear focus | |
clearFocus(); | |
// Hide keyboard if shown | |
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); | |
imm.hideSoftInputFromWindow(this.getWindowToken(), 0); | |
} | |
else | |
{ | |
switch (getState()) | |
{ | |
case STATE_HINT: | |
{ | |
if(LOG) | |
{ | |
Log.d(TAG, "CharacterBox with tag: " + nextCharacterBox.getTag() + " (hint). Proceeding search..."); | |
} | |
// Next character box not editable, keep searching... | |
nextCharacterBox.moveToNextCharacter(); | |
break; | |
} | |
case STATE_INVISIBLE: | |
{ | |
if(LOG) | |
{ | |
Log.d(TAG, "Moving from CharacterBox with tag: " + getTag() + " to: " + nextCharacterBox.getTag() + " (invisible). Requesting focus..."); | |
} | |
// Next character is ediatable, request focus for it. | |
nextCharacterBox.requestFocus(); | |
break; | |
} | |
case STATE_USER_INPUT: | |
{ | |
if(LOG) | |
{ | |
Log.d(TAG, "Moving from CharacterBox with tag: " + getTag() + " to: " + nextCharacterBox.getTag() + " (user input). Requesting focus..."); | |
} | |
// Next character is ediatable, request focus for it. | |
nextCharacterBox.requestFocus(); | |
break; | |
} | |
default: | |
{ | |
if(LOG) | |
{ | |
Log.d(TAG, "Unable to perform moveToNextCharacter(). Undefined CharacterBox state: " + getState()); | |
} | |
break; | |
} | |
} | |
} | |
} | |
public void moveToPreviousCharacter() | |
{ | |
CharacterBox previousCharacterBox = (CharacterBox) getNavigationPrevious(); | |
// If no view defined for next | |
if(previousCharacterBox == null) | |
{ | |
if(LOG) | |
{ | |
Log.d(TAG, "No navigationPrevious defined for CharacterBox with tag: " + getTag()); | |
} | |
// // Hide keyboard if shown | |
// InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); | |
// imm.hideSoftInputFromWindow(this.getWindowToken(), 0); | |
} | |
else | |
{ | |
switch (getState()) | |
{ | |
case STATE_HINT: | |
{ | |
if(LOG) | |
{ | |
Log.d(TAG, "CharacterBox with tag: " + previousCharacterBox.getTag() + " defined as hint. Proceeding search..."); | |
} | |
// previous character box not editable, keep searching... | |
previousCharacterBox.moveToPreviousCharacter(); | |
break; | |
} | |
case STATE_INVISIBLE: | |
{ | |
if(LOG) | |
{ | |
Log.d(TAG, "CharacterBox with tag: " + previousCharacterBox.getTag() + " defined as invisible. Requesting focus..."); | |
} | |
// Previous character is ediatable, request focus for it. | |
previousCharacterBox.requestFocus(); | |
break; | |
} | |
case STATE_USER_INPUT: | |
{ | |
if(LOG) | |
{ | |
Log.d(TAG, "CharacterBox with tag: " + previousCharacterBox.getTag() + " defined as user input. Requesting focus..."); | |
} | |
// Previous character is ediatable, request focus for it. | |
previousCharacterBox.requestFocus(); | |
break; | |
} | |
default: | |
{ | |
if(LOG) | |
{ | |
Log.d(TAG, "Unable to perform moveToPreviousCharacter(). Undefined CharacterBox state: " + getState()); | |
} | |
break; | |
} | |
} | |
} | |
} | |
public void updateBackground(boolean isCurrentlyEditing) | |
{ | |
if(isCurrentlyEditing) | |
{ | |
switch(getState()) | |
{ | |
case STATE_INVISIBLE: | |
case STATE_USER_INPUT: | |
{ | |
setBackgroundResource(android.R.color.holo_blue_bright); | |
break; | |
} | |
case STATE_HINT: | |
default: | |
{ | |
if(LOG) | |
{ | |
Log.d(TAG, "Possible bug. Update background for state: " + getState() + " not defined for editing session."); | |
} | |
break; | |
} | |
} | |
} | |
else | |
{ | |
switch(getState()) | |
{ | |
case STATE_INVISIBLE: | |
case STATE_USER_INPUT: | |
{ | |
setBackgroundResource(android.R.color.holo_blue_dark); | |
break; | |
} | |
case STATE_HINT: | |
{ | |
setBackgroundResource(android.R.color.holo_red_light); | |
break; | |
} | |
default: | |
{ | |
if(LOG) | |
{ | |
Log.d(TAG, "Possible bug. Update background for state: " + getState() + " not defined for non-editing session."); | |
} | |
break; | |
} | |
} | |
} | |
} | |
class CharacterBoxOnFocusChangeListener implements View.OnFocusChangeListener | |
{ | |
@Override | |
public void onFocusChange(View v, boolean hasFocus) | |
{ | |
Log.d(TAG, "Character (" + v.getTag() + ") has focus: " + hasFocus); | |
if(hasFocus) | |
{ | |
CharacterBox.this.setSelection(CharacterBox.this.getText().length()); | |
CharacterBox.this.updateBackground(true); | |
} | |
else | |
{ | |
CharacterBox.this.updateBackground(false); | |
} | |
} | |
} | |
/** | |
* | |
* @author Mac | |
* | |
* Handles only KEYCODE_DEL | |
* | |
*/ | |
class CharacterBoxOnKeyListener implements View.OnKeyListener | |
{ | |
@Override | |
public boolean onKey(View v, int keyCode, KeyEvent event) | |
{ | |
CharacterBox characterBox = (CharacterBox) v; | |
// If backspace pressed | |
if(keyCode == KeyEvent.KEYCODE_DEL) | |
{ | |
// If character box empty | |
if(TextUtils.isEmpty(characterBox.getText())) | |
{ | |
// Move to previous character box | |
characterBox.clearFocus(); | |
characterBox.moveToPreviousCharacter(); | |
} | |
else | |
{ | |
characterBox.setText(""); | |
characterBox.setState(CharacterState.STATE_INVISIBLE); | |
} | |
return true; | |
} | |
else | |
{ | |
// Else condition handled at on text watcher. | |
} | |
return false; | |
} | |
} | |
/** | |
* | |
* @author Mac | |
* | |
* Controls user input except KEYCODE_DEL | |
* | |
*/ | |
class CharacterBoxTextWatcher implements TextWatcher | |
{ | |
private WeakReference<CharacterBox> characterBoxWeak = null; | |
private boolean validToUpdate = false; | |
public CharacterBoxTextWatcher(CharacterBox victimCharacterBox) | |
{ | |
if(victimCharacterBox == null) | |
{ | |
throw new NullPointerException("It is forbidden to use null reference for victimCharacterBox with CharacterBoxTextWatcher"); | |
} | |
else | |
{ | |
characterBoxWeak = new WeakReference<CharacterBox>(victimCharacterBox); | |
} | |
} | |
@Override | |
public void afterTextChanged(Editable s) | |
{ | |
final CharacterBox characterBox = characterBoxWeak.get(); | |
if(characterBox != null) | |
{ | |
String successorString = formatEditable(s); | |
// If successor string not empty|null | |
if(!TextUtils.isEmpty(successorString)) | |
{ | |
Pattern matchPattern = Pattern.compile("[A-Z^ŞİÇÖÜĞ]"); | |
Matcher matcher = matchPattern.matcher(successorString); | |
// If successor string matches given pattern | |
boolean isSuccessorStringValid = matcher.matches(); | |
// If successor string not already exist | |
boolean isPatternFormerlyPrinted = successorString.equals(s.toString());; | |
if(!isPatternFormerlyPrinted) | |
{ | |
if(isSuccessorStringValid) | |
{ | |
characterBox.setText(successorString); | |
} | |
else | |
{ | |
String ancestorString = s.toString().split(successorString)[0]; | |
characterBox.setText(ancestorString); | |
} | |
} | |
else | |
{ | |
characterBox.setState(CharacterState.STATE_USER_INPUT); | |
characterBox.clearFocus(); | |
characterBox.moveToNextCharacter(); | |
} | |
} | |
} | |
} | |
@Override | |
public void beforeTextChanged(CharSequence s, int start, int count, | |
int after) {} | |
@Override | |
public void onTextChanged(final CharSequence s, int start, int before, | |
int count) {} | |
private String formatEditable(Editable e) | |
{ | |
if(e != null) | |
{ | |
if(!TextUtils.isEmpty(e)) | |
{ | |
String formattedEditableString = e.toString().trim(); | |
int lastCharacterIndex = formattedEditableString.length() - 1; | |
String lastCharacter = formattedEditableString.substring(lastCharacterIndex); | |
return lastCharacter.toUpperCase(); | |
} | |
} | |
return ""; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment