äŒæ¥ã®äœæ¥ããã»ã¹ã®ãåå¡ããšã¯ãã³ã©ãã¬ãŒã·ã§ã³ã®ããã®æ©èœããŸããŸãæºåž¯é»è©±ãŸãã¯ã¿ãã¬ããã«ç§»ãããããšãæå³ããŸãã ã¯ãã¹ãã©ãããã©ãŒã ã®ãããžã§ã¯ã管çãµãŒãã¹ã§ãã
Wrikeã®å Žåãã¢ãã€ã«ã¢ããªã±ãŒã·ã§ã³ã®æ©èœãå®å
šã«å®å
šã§äŸ¿å©ã§ããããŠãŒã¶ãŒã®äœæ¥ãå¶éããªãããšãéèŠã§ãã ãããŠãã¿ã¹ã¯èšè¿°ã®å
±åç·šéããµããŒããããªããããã¹ããšãã£ã¿ãŒãäœæããã¿ã¹ã¯ãçºçãããšããæ¢åã®WebViewã³ã³ããŒãã³ãã®æ©èœãè©äŸ¡ããŠãç¬èªã®æ¹æ³ã§ç¬èªã®ãã€ãã£ãããŒã«ãå®è£
ããããšã«ããŸããã
ãŸãã補åã®æŽå²ã«ã€ããŠå°ãã Wrikeã®ã³ã¢æ©èœã®1ã€ã¯ãããšããšã¡ãŒã«çµ±åã§ããã ã¿ã¹ã¯ã®æåã®ããŒãžã§ã³ãããé»åã¡ãŒã«ã§äœæããã³æŽæ°ããä»ã®åŸæ¥å¡ãšäžç·ã«äœæ¥ããããšãã§ããŸããã æçŽã®æ¬æã¯åé¡ã®èª¬æã«å€ããããã以äžã®è°è«ã¯ãã¹ãŠãã®ã³ã¡ã³ãã«ãããŸããã
ã¡ãŒã«ã§ã¯HTMLãã©ãŒãããã䜿çšã§ããããã補åã®åæããŒãžã§ã³ã§ã¯CKEditorã䜿çšããŠã¿ã¹ã¯ã®èª¬æãããã«åŠçããŸããã ããããã³ã©ãã¬ãŒã·ã§ã³æåã®ç°å¢ã§ã¯ãããã¯éåžžã«äžäŸ¿ã§ããããã¥ã¡ã³ãã®å
šäœãŸãã¯äžéšããããã¯ããŠã誰ããæºåããã¿ã¹ã¯ã®èª¬æãäžæžãããªãããã«ããå¿
èŠããããŸãã ãã®çµæããªãã¬ãŒã·ã§ã³å€æïŒOTïŒã®å®è·µãæãäžããçã®ã³ã©ãã¬ãŒã·ã§ã³ã®ããã®ããŒã«ãäœæããããšã«ããŸããã ãã®èšäºã§ã¯ããªããããã¹ãããã¥ã¡ã³ãã®OTã®çè«ãšå®è£
ã«ã€ããŠã¯è©³ããæ€èšããŸããããããã«ã€ããŠã¯æ¢ã«ååãª
è³æããããŸãã ç§ãã¡ã®ããŒã ãã¢ãã€ã«ã¢ããªã±ãŒã·ã§ã³ã®éçºã§ééããå°é£ã®ã¿ãèæ
®ããŸãã
ã¹ããŒããã©ã³ã§ã®å
±åç·šé-ãªãã§ããïŒ
ãã¡ãããããã補åã®éèŠãªæ©èœã§ãªãéããããããå¿
èŠã¯ãããŸããã ãã¹ãŠã®ãã©ãããã©ãŒã ã§æå€§éã®åºæ¬æ©èœãæäŸãããšããäžè¬çãªç®æšã«å ããŠãããã«ã€ããŠèããªããã°ãªããªãã£ãããã€ãã®ããå
·äœçãªçç±ããããŸããã
- OTãå®è£
ããã«ã¯ãå
±åç·šéããµããŒãããç¹å®ã®åœ¢åŒã§ããã¥ã¡ã³ããä¿åããå¿
èŠããããŸãã ãã¬ãŒã³ããã¹ãã®å Žåãããã«ã¯ç¹å¥ãªåœ¢åŒã¯ãããŸãããåãªãæååã§ãã ãã ãããªããããã¹ãïŒæžåŒä»ãããã¹ãïŒã®å Žåãã¹ãã¬ãŒãžåœ¢åŒã¯ããè€éã«ãªããŸãã
- ããã¥ã¡ã³ããå£ãããšãªãããŸãä»ã®ãŠãŒã¶ãŒãåãæéã«è¡ãããšãã§ãã倿Žãšç«¶åããããšãªããã¢ãã€ã«ã¯ã©ã€ã¢ã³ãã«ãã£ãŠè¡ããã倿Žãä¿åããæ¹æ³ãå¿
èŠã§ãã ãããã¯ãOTã¢ã«ãŽãªãºã ã«ãã£ãŠæ£ç¢ºã«è§£æ±ºãããã¿ã¹ã¯ã§ãã
- ãã©ã°ã©ã2ã®æ¡ä»¶ãæºããããã«OTã¢ã«ãŽãªãºã ãã¢ãã€ã«ãã©ãããã©ãŒã ã«è»¢éããå¿
èŠããããããæ¬æ Œçãªå
±åç·šéãè¡ãããã«ããã以äžå€§ããªåŽåã¯å¿
èŠãããŸããã
ãã®ãããåºæ¬çãªæ©èœãšããŠã®ã¿ã¹ã¯ã®ãªããããã¹ãèšè¿°ãç¹å®ã®ããã¥ã¡ã³ã圢åŒãšåæãããã³ã«ããµããŒãããå¿
èŠæ§ãããã®ã§ã解決çãèŠã€ããŸãããã
å®è£
ãªãã·ã§ã³
ã³ã©ãã¬ãŒã·ã§ã³ã³ã³ããŒãã³ãã®å®è£
ã«ã€ããŠã¯ãã§ã«çµéšããããŸããããAndroidã«è»¢éããæ¹æ³ãçè§£ããå¿
èŠããããŸããã ç·šéè
ã®èŠä»¶ã«å€§ããäŸåããŠãããäžè¬çã«ã¯æ¬¡ã®2ã€ããããŸããã
- åºæ¬çãªæžåŒèšå®ããªã¹ããç»åãšè¡šã®æ¿å
¥ã
- ããã¹ãèªäœãšãã®ãã©ãŒãããã®äž¡æ¹ã§å€æŽãè¡ãã远跡ã§ããAPIã
æ¹æ³1ïŒWeb補åã®æ¢åã®ã³ã³ããŒãã³ãã䜿çšãã
å®éãæ¢ã«æã£ãŠããã³ã³ããŒãã³ãã䜿çšããŠãWebViewã«ã©ããããããšãã§ããŸãã å©ç¹ã®1ã€ã¯çµ±åã®å®¹æãã§ããããã¯ãå®è³ªçã«ãã¹ãŠã®ãšãã£ã¿ãŒã³ãŒããã¹ã¯ãªããã«å«ãŸããŠãããAndroid / iOSéçºè
ã¯WebViewã©ãããŒã®ã¿ãå®è£
ã§ããããã§ãã
ããã«ãContentEditableããã¥ã¡ã³ãã§åäœããã¡ã€ã³ã¢ããªã±ãŒã·ã§ã³ã®æ¢åã®ã³ã³ããŒãã³ãã¯ãOSãšãã³ããŒã®ããŒãžã§ã³ã«ãã£ãŠã¯éåžžã«äžå®å®ã§ããããšãæããã«ãªããŸããã å Žæã®ãšããŸããã¯ãªãã°ãæŽèµ°ããŸãããã倧éšåã¯ããã¹ãã®åŒ·èª¿è¡šç€ºãšå
¥åã®æ©èœãããã³ãã©ãŒã«ã¹ãšããŒããŒãã®æ¬ èœã®æ©èœã®åšãã«ãããã¢ããããŸããã
ContentEditableã®åé¡ãåé¿ããããããšãã£ã¿ãŒã®ããã³ããšã³ããšããŠ
CodeMirrorã䜿çšããããšããŸããããããŒããŒãããã®ãã¹ãŠã®ã€ãã³ããåŠçããç¬èªã«ã¬ã³ããªã³ã°ãããããAndroidã§ã¯ããã«å®å®ããŠåäœããŸãã ãã¡ãããã€ãã¹ããããŸããããIMEã®ããŒæŒäžã€ãã³ãã®åŠçã«æªåé«ã倿ŽãçŸãããŸã§ãç°¡åãªåé¿çãšããŠéåžžã«ããŸãæ©èœããŸããããã®åé¡ã«ã€ããŠã¯ã
ããã§è©³ãã説æã
ãŸã ã ç°¡åã«èšãã°-LatinIMEã䜿çšããå ŽåãKEYCODE_DELã®ã€ãã³ãã¯éä¿¡ãããŸããã
ããã¯ãŠãŒã¶ãŒã«ãšã£ãŠäœãæå³ããŸããïŒ [åé€]ãã¯ãªãã¯ããŠãäœãèµ·ãããŸãããã€ãŸãããšãã£ã¿ãŒã¯æ£åžžã«åäœããããã¹ããå
¥åããæžåŒèšå®ãé©çšã§ããŸããã©ã®ããã«èãããŠããããã¹ãã¯åé€ã§ããŸããã ãã®åé¡ã®å¯äžã®è§£æ±ºçã¯ããšããããæ¬¡ã®ã³ãŒããå«ãŸããŠããŸããã
@Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { BaseInputConnection baseInputConnection = new BaseInputConnection(this, false) { @Override public boolean sendKeyEvent(KeyEvent event) { if (needsKeyboardFix() && event.getAction() == KeyEvent.ACTION_MULTIPLE && event.getKeyCode() == KeyEvent.KEYCODE_UNKNOWN) { passUnicodeCharToEditor(event); return true; } return super.sendKeyEvent(event); } @Override public boolean deleteSurroundingText(int beforeLength, int afterLength) { if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) && (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) && (beforeLength == 1 && afterLength == 0)) {
InputType.TYPE_NULLã¯åæã«IMEããç°¡ç¥åãããã圢åŒã«å€æããInputConnectionãå¶éã¢ãŒãã§åäœããŠããããšã瀺ããŸããã€ãŸããã³ããŒ/貌ãä»ããèªåä¿®æ£/èªåè£å®ããžã§ã¹ãã£ãŒã䜿çšããããã¹ãå
¥åããªãããšãæå³ããŸãããåæã«ãã¹ãŠã®ããŒããŒãã€ãã³ããåŠçã§ããŸãã
ãã®çµæãWebã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšãããšãã£ã¿ãŒã®ææ°ã®å®è£
ã«ã¯ãæ¬¡ã®æ¬ ç¹ããããŸããã
- ããŠã³ããŒãé床ãé
ã
- é«åºŠãªIMEæ©èœãžã®ã¢ã¯ã»ã¹ã®æ¬ åŠïŒã³ããŒ/貌ãä»ãããªãŒãã³ã³ããªãŒã/ãªãŒãã³ã¬ã¯ãããžã§ã¹ãã£ãŒå
¥åïŒ;
- å Žåã«ãã£ãŠã¯ãAPIã®ããŸããŸãªããŒãžã§ã³ã§ã®WebViewã®ããŸããŸãªå®è£
ããã³äžéšã®ãã³ããŒã«ãããã®ã³ã³ããŒãã³ãã®å€æŽã®ããã«ãåäœãäžå®å®ã«ãªããŸãã
- éåžžãWebViewã¯ãç¹ã«ã¡ã¢ãªãå°ãªãããã€ã¹ã§ã¯é·æéã¡ã¢ãªã«ãšã©ãŸããŸããããŸããã¢ããªã±ãŒã·ã§ã³ãæå°åãããã°ããããŠããåèµ·åãããšãã»ãšãã©ã®å ŽåãWebViewãå床åæåããå¿
èŠããããŸãã
- ã³ãŒãã«ã¯å€æ°ã®æŸèæãããããã®æ°ã¯æéãšãšãã«å¢å ããŸããã
ãã®ãããªãšãã£ã¿ãŒã®å®è£
ãç¶æããããšã¯å®¹æã§ã¯ãªãããšãèªèããèšèŒãããŠããæ¬ ç¹ãšå¶éãèæ
®ããŠããã©ãŒããããããããã¹ãã䜿çšã§ãããã€ãã£ãã³ã³ããŒãã³ããéçºããããšã«ããŸããã
æ¹æ³2ïŒãã€ãã£ãå®è£
ãã€ãã£ãå®è£
ã®å Žåãæ¬¡ã®2ã€ã®åé¡ã解決ããå¿
èŠããããŸãã
- UIãšãã£ã¿ãŒãã€ãŸãããã©ãŒããããšç·šéã«åºã¥ããŠããã¹ãã衚瀺ããŸãã
- ããã¥ã¡ã³ã圢åŒã倿Žè¿œè·¡ãããã³ãµãŒããŒãšã®ããŒã¿äº€æãåŠçããŸãã
æåã®åé¡ã解決ããããã«ãè»èŒªãåçºæããå¿
èŠã¯ãããŸãã-Androidã¯å¿
èŠãªããŒã«ãã€ãŸãEditTextã³ã³ããŒãã³ããšããã¹ãã®ã©ãã«ä»ããèšè¿°ããSpannableã€ã³ã¿ãŒãã§ãŒã¹ãæäŸããŸãã
2çªç®ã®ã¿ã¹ã¯ã¯ãOTã¢ã«ãŽãªãºã ãJavaScriptããJavaã«è»¢éããããšã§è§£æ±ºãããããã§ã®ããã»ã¹ã¯éåžžã«ééçã§ãã
EditTextã§ãªããããã¹ãã衚瀺ãã
Androidã«ã¯ãããã¹ãããŒã¯ã¢ãããèšå®ã§ãããã°ããã
Spannableã€ã³ã¿ãŒãã§ã€ã¹ããããŸãã ããŒã¯ã¢ããããã»ã¹èªäœã¯éåžžã«ç°¡åã§ããç¹å¥ãªSpannableStringBuilderã¯ã©ã¹ã䜿çšããå¿
èŠããããŸãããã®ã¯ã©ã¹ã䜿çšãããšãããã¹ããèšå®/倿Žããã¡ãœãããä»ããŠããã¹ãã®æå®ã»ã¯ã·ã§ã³ã®ã¹ã¿ã€ã«ãèšå®ã§ããŸãã
setSpan(Object what, int start, int end, int flags).
æåã®ãã©ã¡ãŒã¿ãŒã¯ã¹ã¿ã€ã«ãèšå®ããã ãã§ãã android.text.styleããã±ãŒãžã®1ã€ä»¥äžã®ã€ã³ã¿ãŒãã§ãŒã¹ïŒCharacterStyleãUpdateAppearanceãUpdateLayoutãParagraphStyleãªã©ïŒãå®è£
ããã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ã§ãªããã°ãªããŸããã ããã©ã«ãã®ã¹ã¿ã€ã«ã®ã»ããã¯éåžžã«åºããæåãã©ãŒãããïŒStyleSpanãUnderlineSpanïŒã®å€æŽãããã¹ããµã€ãºã®èšå®ïŒRelativeSizeSpanïŒãäœçœ®ã®å€æŽïŒAlignmentSpanïŒãããµããŒãã€ã¡ãŒãžïŒImageSpanïŒããã³ã¯ãªãã¯å¯èœãªããã¹ãïŒClickableSpanïŒãŸã§ã§ãã
æåŸã®ãã©ã¡ãŒã¿ãŒã¯ãã©ã°ãèšå®ããŸãããã®åœ¹å²ã«ã€ããŠã¯ä»¥äžã§èª¬æããŸãã ããšãã°ãããã¯ããã¹ãå
šäœã®è²ã倿Žããæ¹æ³ã§ãã
SpannableStringBuilder ssb = new SpannableStringBuilder(text); ssb.setSpan(new ForegroundColorSpan(Color.BLUE), 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); textView.setText(ssb, TextView.BufferType.SPANNABLE);
ãã®ãããå
¥åã«ã¯ç¹å®ã®åœ¢åŒã®ããã¹ãããããŸãããåºåã«ã¯ãã®è¡šçŸãSpannableãªããžã§ã¯ãã®åœ¢åŒã§ååŸããEditTextã«æž¡ãå¿
èŠããããŸãã ãã®å Žåãããã¥ã¡ã³ãã¯å±æ§ä»ãæååã®åœ¢åŒã§ãµãŒããŒããç¹å¥ãªåœ¢åŒã§ååŸãããŸããOTçšã®ã©ã€ãã©ãªã䜿çšããŠãã®æååãè§£æããããã¹ãã®æå®ãããéšåã«å±æ§ãé©çšããå¿
èŠããããŸãã ã¹ã¿ã€ã«ã«å¿ããŠãããã¹ãã®ã©ãã«ä»ãããŠãŒã¶ãŒã®æåŸ
ã«åãããã«ãæ£ãããã©ã°ãèšå®ããå¿
èŠããããŸãã
ãã©ã°SPAN_EXCLUSIVE_INCLUSIVEã§ã¹ã¿ã€ã«ãããŒã¯ãããšãééã®æåŸã«å
¥åãããããã¹ãã«é©çšãããŸãããæåã«ã¯é©çšãããŸããã ããšãã°ãUnderlineSpan + SPAN_EXCLUSIVE_INCLUSIVEã¹ã¿ã€ã«ãèšå®ãããŠããéé[10ã20]ããããŸãã ãã®å Žåãäœçœ®9ã«ããã¹ããå
¥åãããšãUnderlineSpanã¹ã¿ã€ã«ã¯é©çšãããŸããããäœçœ®20ã«ããã¹ããå
¥åãå§ãããšãã¹ã¿ã€ã«ãã«ããŒããééãæ¡å€§ããŠ[10ã21]ã«ãªããŸãã åœç¶ãããã¯ã€ã³ã©ã€ã³æžåŒèšå®ïŒå€ªå/æäœ/äžç·ãªã©ïŒã«åœ¹ç«ã¡ãŸãã
SPAN_EXCLUSIVE_EXCLUSIVEãã©ã°ã䜿çšããå Žåãã¹ã¿ã€ã«ééã¯äž¡ç«¯ã§å¶éãããŸãã ããã¯ãããšãã°ãªã³ã¯ã«é©ããŠããŸã-ãªã³ã¯ã®çŽåŸã«ããã¹ãã®æ¿å
¥ãéå§ããå Žåããªã³ã¯ã¹ã¿ã€ã«ãé©çšããªãã§ãã ããã
ãã©ã°SPAN_EXLUSIVE_INCLUSIVEããã³SPAN_EXCLUSIVE_EXCLUSIVEã䜿çšãããšããŠãŒã¶ãŒã®æåŸ
ã«å¿ããŠããã¹ããå
¥åãããšãã®æžåŒèšå®åäœãå¶åŸ¡ã§ããŸãã ããšãã°ãå€ªåæžåŒèšå®ã¢ãŒãããªã³ã«ããå Žåãå
¥åããã¹ãã¯å€ªåã®ãŸãŸã«ãªããŸãã ãŸãããªã³ã¯ãäœæããå ŽåãæåŸã«ããã¹ãã远å ããŠããªã³ã¯ã®å¢çã¯æ¡å€§ãããŸããã
BulletSpanã䜿çšããŠãªã¹ãã¢ã€ãã ã衚瀺ã§ããŸãããé åºã®ãªããªã¹ãã«ã®ã¿é©ããŠããŸãã çªå·ä»ããå¿
èŠãªå Žåã¯ãLeadingMarginSpanããã³UpdateAppearanceã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããç¬èªã®ã¯ã©ã¹ãèšè¿°ããŠãdrawLeadingMarginã¡ãœããã§ãªã¹ãã€ã³ãžã±ãŒã¿ãŒãåžæã©ããã«ã¬ã³ããªã³ã°ã§ããŸãã
ã«ã¹ã¿ã ã¹ã¿ã€ã«åŠç
ãšãã£ã¿ãŒã¯ããŠãŒã¶ãŒããã©ãŒããããé©çšã§ããããã«ããå¿
èŠãããããšã¯æããã§ããããã«ã¯ä»¥äžãå«ãŸããŸãã
- éžæããããã¹ãã«æ°ããã¹ã¿ã€ã«ã远å ãã
- ã«ãŒãœã«äœçœ®ã«æ°ããã¹ã¿ã€ã«ãæ¿å
¥ãã
- ç·šéäžã«çŸåšã®ã¹ã¿ã€ã«ãé©çšããŸãã
ãŸãããšãã£ã¿ãŒã§ãµããŒããããŠããã¹ã¿ã€ã«ã®ã©ããã«ãã¿ã³ãé
眮ããå¿
èŠããããŸãã ããããã¢ã¯ãã£ããã£ããŒã«ããŒã«é
眮ããããšã¯ãAndroid MarshmallowããªãªãŒã¹ããããŸã§å®çšçã§ã¯ãããŸããã§ããã ããã©ã«ãã§ã¯ãããã¹ããéžæãããšãã«ã³ã³ããã¹ãã¡ãã¥ãŒã«åãããŒã«ããŒã䜿çšããããããéžæããããã¹ãã®ã¹ã¿ã€ã«ãéžæããããšã¯ã§ããŸããã ãã®ãããç»é¢äžéšã®ããŒã«ããŒã«ããããé
眮ã§ããŸãã ã¹ã¿ã€ã«ãã¿ã³ãã¯ãªãã¯ãããšããšãã£ã¿ãŒã®çŸåšã®ç¶æ
ãå€å¥ããéžæããããã¹ãã«ã¹ã¿ã€ã«ãé©çšããããã«ãŒãœã«äœçœ®ã§ãã®ã¹ã¿ã€ã«ãäžæçãªãã®ãšããŠèšæ¶ããå¿
èŠããããŸãã
private void onApplyInlineAttributeToSelection(int selectionStart, int selectionEnd, TextAttribute attribute) { int selectionStart = mEditText.getSelectionStart(); int selectionEnd = mEditText.getSelectionEnd(); if (!mEditText.hasSelection()) {
mTempAttributesã¯ãTempAttributesã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ã§ãã ãŠãŒã¶ãŒãéžæãããã®äœçœ®ã®å±æ§ã®ã»ãããå®çŸ©ããŸãã ãã®å€æ°ã¯ã䜿çšåŸãŸãã¯ã«ãŒãœã«äœçœ®ã®å€æŽæã«ãŒãã«ãªã»ãããããŸãã
static class TempAttributes { private final int mPos; private final Map<AttributeName, TextAttribute> mAttributeMap = new HashMap<>(); public TempAttributes(int pos) { mPos = pos; } public int getPos() { return mPos; } public Collection<TextAttribute> getAttributes() { return mAttributeMap.values(); } public void addAttribute(TextAttribute attribute) { AttributeName name = attribute.getAttributeName(); TextAttribute oldAttribute = mAttributeMap.get(name); if (oldAttribute != null && !oldAttribute.isNull()) { attribute.nullify(); } mAttributeMap.put(name, attribute); } }
ãŠãŒã¶ãŒãããŒã«ããŒã®ç¹å®ã®ã¹ã¿ã€ã«ã«å¯Ÿå¿ãããã¿ã³ãã¯ãªãã¯ããããããã¹ããéžæãããŠããªãå Žåããã®å Žåããã®ã¹ã¿ã€ã«ãçŸåšã®ã«ãŒãœã«äœçœ®ã«ãäžæããšããŠä¿åãããã®äœçœ®ã«ããã¹ããå
¥åãããšãã«é©çšããå¿
èŠããããŸãã 詳现ã«ã€ããŠã¯ã以äžãã芧ãã ããã
ããã¹ããéžæããããããã®ã¹ã¿ã€ã«ãéžæããééã«æ¢ã«ååšãããã©ããã倿ããå¿
èŠããããŸãã ããã§ãªãå ŽåããŸãã¯éšåçã«ããã¹ãŠã®æ¢åã®ã¹ãã³ãçµåãããã®ã¹ã¿ã€ã«ã§ééãå®å
šã«ã«ããŒããå¿
èŠããããŸãã ããå Žåã¯ãééãã察å¿ããã¹ãã³ãåé€ããå¿
èŠã«å¿ããŠåå²ããŸãã
äŸ1ããã¹ãããããŸãïŒ
Quick brown
fox ã
倪å[0.4]ãšå€ªå[12.14]ã®2ã€ã®ã¹ãã³ããããŸãã ãŠãŒã¶ãŒããã¹ãŠã®ããã¹ããéžæããŠå€ªåã¹ã¿ã€ã«ãé©çšããå Žåãæçµçã«ã¯ééå
šäœãã«ããŒããå¿
èŠããããŸãã ãããè¡ãã«ã¯ãäž¡æ¹ã®ã¹ãã³ãåé€ããŠæ°ãã倪å[0ã14]ã远å ãããã2çªç®ã®ã¹ãã³ãåé€ããŠæåã®ã€ã³ã¿ãŒãã«ãééã®çµãããŸã§å»¶é·ããŸãã
äŸ2ããã¹ãããããŸãïŒ
Quick brown fox ã
倪å[0ã14]ã®1ã€ã®ã¹ãã³ããããŸãã ãŠãŒã¶ãŒãããã¹ã[4ã12]ãéžæããããŒã«ããŒã§å€ªåã¹ã¿ã€ã«ãéžæããå Žåãã¹ã¿ã€ã«ã¯éžæç¯å²ã«å®å
šã«ååšãããããééããã¹ã¿ã€ã«ãåé€ããå¿
èŠããããŸãã ãããè¡ãã«ã¯ãééã2ã€ã®éšåã«åå²ããŸããéžæãå§ãŸãåã«ééå
šäœ[0ã14]ãçããïŒ[0ã4]ïŒãéžæç¯å²ã®æåŸããããã¹ãã®çµãããŸã§æ°ããééã远å ããŸãïŒ[4ã12]ïŒã
ããã¥ã¡ã³ãã®å€æŽã远跡ãã
ãŠãŒã¶ãŒã®å€æŽãæ£ãã远跡ããŠOTã¢ã«ãŽãªãºã ã«ããã£ãŒããããã«ã¯ããšãã£ã¿ãŒããããã远跡ã§ããå¿
èŠããããŸãã ãããè¡ãã«ã¯ãTextWatcherã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšãããŸããEditTextã§å€æŽãçºçãããã³ã«ããã®ã€ã³ã¿ãŒãã§ã€ã¹ã®beforeTextChangedãonTextChangedãafterTextChangedã¡ãœãããé çªã«åŒã³åºãããäœãã©ãã§å€æŽããããã倿ã§ããŸãã
private boolean mIgnoreNextTextChange = false; private int mCurrentPos; private String mOldStr = null; private String mNewStr = null;
setTextïŒCharSequenceïŒãä»ããŠãšãã£ã¿ãŒã«æåã«ããã¹ããã€ã³ã¹ããŒã«ãããšãTextWatcherãããã«é¢ããéç¥ãåãåããããããã°ã©ã ã«ããããã¹ãã®ã€ã³ã¹ããŒã«ã¯æ¬¡ã®ããã«ãªããŸãã
mEditTextWatcher.ignoreNextTextChange(true); mEditText.setText(builder); mEditTextWatcher.ignoreNextTextChange(false);
mOldStr倿°ãšmNewStr倿°ã¯ãããããå€ãè¡ãšæ°ããè¡ãæ ŒçŽããŸããmCurrentPosã¯ã倿Žãçºçããäœçœ®ã瀺ããŸãã ããšãã°ããŠãŒã¶ãŒã10æ¡ç®ã«ãaããšããæåã远å ããå Žåã
mOldStr = null; mNewStr = "a"; mCurrentPos = 10;
ãã ããããããªãã¥ã¢ã³ã¹ããããŸã-èªåä¿®æ£ã«ããããã¹ããæ¿å
¥ããå Žåããããã®å€ã«ã¯åèªã®å
é ãå«ãŸããå ŽåããããŸãã ããšãã°ãããã¹ãããããã¹ãããšããåèªã§å§ãŸãããŠãŒã¶ãŒã3çªç®ã®æåããsãã«çœ®ãæããå ŽåãIMEã¯ãã®å€æŽã次ã®ããã«å ±åã§ããŸãã
mOldStr = "Tex"; mNewStr = "Tes"; mCurrentPos = 0;
ãã®å Žåãè¡ã®å
é ããåãæååãã«ããããå¿
èŠããããŸãã
æçµçã«ãTextWatcherã䜿çšããŠãæ£ç¢ºã«äœãèµ·ãã£ãã®ããæç¢ºã«å€æã§ããŸããããã¹ãã眮æãåé€ããŸãã¯è¿œå ãããŸããã ãŠãŒã¶ãŒãããã¹ãããã®äœçœ®ã«è¿œå ããããæ¢åã®ããã¹ãã®äžéšããããã¡ãŒã®ããã¹ãã§çœ®ãæããå Žåãã«ãŒãœã«äœçœ®ã«ãã屿§ã远å ãããããã¹ãã«é©çšããå¿
èŠããããŸãã ãããè¡ãã«ã¯ã空ã«ãªã£ããªããžã§ã¯ãïŒs.getSpanStartïŒspanïŒ== s.getSpanEndïŒspanïŒïŒãé€å€ããããšãå¿ããã«ãã«ãŒãœã«äœçœ®ã«ãããã¹ãŠã®Spannableãªããžã§ã¯ããæ€çŽ¢ããSpannableãªããžã§ã¯ãèªäœãåé€ããŠã€ã³ã©ã€ã³å±æ§ã®ã¿ã§ãã£ã«ã¿ãªã³ã°ããŸãïŒå€ªåãæäœãªã©ïŒã ããã«ãããŒã«ããŒã§ãŠãŒã¶ãŒãéžæããã¹ã¿ã€ã«ïŒmTempAttributesïŒã«å¯Ÿå¿ãã屿§ã远å ãããŸãã
public void afterTextChanged(Editable s) {
ãã®çµæã倿Žãçºçããäœçœ®ãããããã®äœçœ®ã®å€ãããã¹ããšæ°ããããã¹ããããã³æ°ããããã¹ãã«é©çšããå¿
èŠãããã€ã³ã©ã€ã³å±æ§ãèªèãããŸãã ãã®åŸã远å ã®åŠçã远å ã§ããŸãã ããšãã°ããŠãŒã¶ãŒããªã¹ãã®æåŸã®é
ç®ã®æåŸã«æ¹è¡ãæ¿å
¥ããå Žåããªã¹ãã®çŸåšã®ã«ãŒãœã«äœçœ®ã«æ°ããé
ç®ãæ¿å
¥ããŠãªã¹ããç¶ç¶ã§ããŸãã æçµçã«ã倿Žã®ãªã¹ãããããã®ããŒã¿ããã³ã³ãã€ã«ããããµãŒããŒã«éä¿¡ãããŸãã
ãšãã£ã¿ãŒã§å€æŽã远跡ããå Žåããã¹ãŠã®ããã©ã«ãã¹ã¿ã€ã«ã«ã©ãããŒã䜿çšããããšããå§ãããŸãã ããšãã°ãUnderlineSpanã®ä»£ããã«ãUnderlineSpanãç¶æ¿ããCustomUnderlineSpanã¯ã©ã¹ã䜿çšããŸãããã¡ãœããã¯ãªãŒããŒã©ã€ããããŸããã ãã®ã¢ãããŒãã«ãããã¯ã©ã¹ã¯EditTextã«ãã£ãŠäœ¿çšãããã¹ã¿ã€ã«ããããããã®ãã¹ã¿ã€ã«ãäžæã«åé¢ã§ããŸãã ããšãã°ããªãŒãã³ã¬ã¯ããæå¹ã«ãªã£ãŠããå Žåãåèªã®ç·šéæã«EditTextã¯UnderlineSpanã¹ã¿ã€ã«ã远å ããèŠèŠçã«ç·šéæã«åèªã«äžç·ãåŒãããŸãã
APIã®ç°ãªãããŒãžã§ã³ãšã®äºææ§ã«ã€ããŠ
Android KitKatããåã®APIããŒãžã§ã³ã§ã¯ãç·šéæã«ã¹ãããã«ããã¹ãã®ãªãŒããŒã¬ã€ã«
åé¡ããããŸãã TextViewã®ããŒããŠã§ã¢ã¢ã¯ã»ã©ã¬ãŒã·ã§ã³ãç¡å¹ã«ããããšã§è§£æ±ºããŸãïŒããããããããä¿®æ£ããä»ã®æ¹æ³ããããŸã-ã³ã¡ã³ãã®ææ¡ã¯å€§æè¿ã§ãïŒã
mEditText.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
ãã ãããã®ãã©ãŒã ã§ã¯ãViewå
šäœãã¡ã¢ãªã«ã¬ã³ããªã³ã°ãããããïŒãæç»ãã£ãã·ã¥ã«åãŸããªãã»ã©å€§ãããã¥ãŒãïŒãTextViewèªäœãã¹ã¯ããŒã«ã§ããããã«ããå¿
èŠããããããTextViewãScrollViewã«é
眮ã§ããŸããã
mEditText.setVerticalScrollBarEnabled(true); mEditText.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);
ãããã«
WebViewã§ã®ãšãã£ã¿ãŒã®å®è£
ã«èŠãã¿ããã®ã¢ãããŒãã®è¡ãè©°ãŸãã«æ°ä»ããç§ãã¡ã¯ãå
±åããã¹ãç·šéã®å°é£ã§ã¯ãããããªãè峿·±ãã¿ã¹ã¯ã解決ãããã€ãã£ãã³ã³ããŒãã³ããéçºããããšã«æåããŸããã ããã«ãããã¢ããªã±ãŒã·ã§ã³ã®äœ¿ãããããåäžãããŠãŒã¶ãŒã®çç£æ§ãåäžããŸããã çµæã¯
ãGoogle Playããã¢ããªã±ãŒã·ã§ã³
ãããŠã³ããŒãããããšã§æšå®ã§ããŸãã
