Idea-深入github AndroidAndroid技术知识Android开发

Idea-深入github Android(二)

2017-04-21  本文已影响58人  AnalyzeSystem

Keywords: Android TextView

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

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

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就会有警告提示


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的一些子类的具体用途,看过之后真相即将明了


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

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

上一篇下一篇

猜你喜欢

热点阅读