Idea-深入github Android(二)

Keywords: Android TextView

github:https://github.com/rockerhieu/emojicon

emojicon开源库是一个关于表情输入相关的,主要是Span运用,这里把代码分为两部分学习emoji、其他。先从emoji包开始,这里面主要是一些基础数据和Emojicon类

Idea-深入github Android(二)_第1张图片

Nature、Objects、People、Places、Symbols都是基础数据略过,Emojicon类提供了上面这些基础数据的转换方法,实现了序列化,那么,为什么要序列化?

  • 永久性保存对象,保存对象的字节序列到本地文件中;

  • 通过序列化对象在网络中传递对象;

  • 通过序列化在进程间传递对象。

以上都不是重点,重点是在Emojicon类中发现了一段诡异的代码(对自己而言),枚举为什么要这样用呢,为什么要用注解呢?


@IntDef({DynamicDrawableSpan.ALIGN_BASELINE, DynamicDrawableSpan.ALIGN_BOTTOM})
public @interface Alignment {
 
    }

@IntDef({TYPE_UNDEFINED, TYPE_PEOPLE, TYPE_NATURE, TYPE_OBJECTS, TYPE_PLACES, TYPE_SYMBOLS})
@Retention(RetentionPolicy.SOURCE)
public @interface Type {

    }
public static final int TYPE_UNDEFINED = 0;
public static final int TYPE_PEOPLE = 1;
public static final int TYPE_NATURE = 2;
public static final int TYPE_OBJECTS = 3;
public static final int TYPE_PLACES = 4;
public static final int TYPE_SYMBOLS = 5;

public static Emojicon[] getEmojicons(@Type int type) {
    switch (type) {
        case TYPE_PEOPLE:
            return People.DATA;
        case TYPE_NATURE:
            return Nature.DATA;
        case TYPE_OBJECTS:
            return Objects.DATA;
        case TYPE_PLACES:
            return Places.DATA;
        case TYPE_SYMBOLS:
            return Symbols.DATA;
        }
    throw new IllegalArgumentException("Invalid emojicon type: " + type);
        
    }

带着疑问差了些许资料,从内存效率方面考虑,上面这种方式最优,这里不再重复叙述,提供相关资料链接,有兴趣者可以自行参阅

http://developer.android.com/training/articles/memory.html#Overhead

https://noobcoderblog.wordpress.com/2015/04/12/java-enum-and-android-intdefstringdef-annotation/

这里再多提一点,注解在开发中有很大用处,android-support-annotations库用处很大,例如@Nullable 会对代码进行检查,如果传入值为null就会有警告提示

Idea-深入github Android(二)_第2张图片

Utils类主要是关于keyboardView 、屏幕的宽高获取,还有个生成viewId方法,这里面用到了一个相对陌生的类AtomicInteger,一个提供原子操作的Integer的类。在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。

AtomicInteger相关API

 //获取当前的值
 
 public final int get()
 
 //取当前的值,并设置新的值
 
  public final int getAndSet(int newValue)
 
 //获取当前的值,并自增
 
  public final int getAndIncrement() 
 
 //获取当前的值,并自减
 
 public final int getAndDecrement()
 
 //获取当前的值,并加上预期的值
 
 public final int getAndAdd(int delta)

Emojicon库主要用的控件组合:Fragment+ViewPager+GridView,这个流程大致梳理一下:Tab被点击了执行ViewPager的Item切换,即切换Fragment,表情GridViewItem被点击了执行回调函数

 @Override
    public void onItemClick(AdapterView parent, View view, int position, long id) {
        if (mOnEmojiconClickedListener != null) {
            mOnEmojiconClickedListener.onEmojiconClicked((Emojicon) parent.getItemAtPosition(position));
        }
    }

onEmojiconClicked主要是回调输入内容,我们通过EmojiconsFragment.input(mEditEmojicon, emojicon)方法完成Text赋值

public static void input(EditText editText, Emojicon emojicon) {
        if (editText == null || emojicon == null) {
            return;
        }

        int start = editText.getSelectionStart();
        int end = editText.getSelectionEnd();
        if (start < 0) {
            editText.append(emojicon.getEmoji());
        } else {
            editText.getText().replace(Math.min(start, end), Math.max(start, end), emojicon.getEmoji(), 0, emojicon.getEmoji().length());
        }
    }

以上流程主要是对于直接的EditText而言,而他的直接、间接子类TextView 、AppCompatMultiAutoCompleteTextView又略有不同,提供了自定义控件:EmojiconTextView、EmojiconMultiAutoCompleteTextView,他们主要是修改setText、setEmojiconSize方法实现,这两个方法都涉及到一个类EmojiconHandler,他们都调用了EmojiconHandler.addEmojis(),由于addEmojis函数过长就不贴代码了,这里面主要是Span的包装,最后设置到控件,所以得出一个结论:

Emojicon库的核心就是自定义EmojiconSpan和自定义组合控件。

EmojiconSpan继承DynamicDrawableSpan,那么问题来了,Span的直接子类那么多为什么非要DynamicDrawableSpan?我们来看看Span的一些子类的具体用途,看过之后真相即将明了

  • BackgroundColorSpan 背景色

  • ClickableSpan 文本可点击,有点击事件

  • ForegroundColorSpan 文本颜色(前景色)

  • MaskFilterSpan 修饰效果,如模糊(BlurMaskFilter)、浮雕(EmbossMaskFilter)

  • MetricAffectingSpan 父类,一般不用

  • RasterizerSpan 光栅效果

  • StrikethroughSpan 删除线(中划线)

  • SuggestionSpan 相当于占位符

  • UnderlineSpan 下划线

  • AbsoluteSizeSpan 绝对大小(文本字体)

  • DynamicDrawableSpan 设置图片,基于文本基线或底部对齐。

  • ImageSpan 图片

  • RelativeSizeSpan 相对大小(文本字体)

  • ReplacementSpan 父类,一般不用

  • ScaleXSpan 基于x轴缩放

  • StyleSpan 字体样式:粗体、斜体等

  • SubscriptSpan 下标(数学公式会用到)

  • SuperscriptSpan 上标(数学公式会用到)

  • TextAppearanceSpan 文本外貌(包括字体、大小、样式和颜色)

  • TypefaceSpan 文本字体

  • URLSpan 文本超链接


以上内容为上午学习所得,分享出来,希望各位朋友喜欢。如果你觉得博主这篇博客还行,还请不吝"❤"一个,谢谢!

交流群初创,欢迎各位加入

你可能感兴趣的:(Idea-深入github Android(二))