闲得蛋疼,折腾折腾android源码包下面widget包下面很少用以及几乎没听说过的控件(针对自己而言,莫要批斗(⊙o⊙)哦丫)。


TextClock

效果图

实现原理

TextClock继承自TextView,扩展自定义属性三个(主要是显示格式相关属性控制)

在onAttachedToWindow和onDetachedFromWindow方法注册了广播和取消注册,监听时间发生变化了,接收到广播,调用onTimeChanged方法更新UI,下面是简要代码块

    @Override    protected void onAttachedToWindow() {        super.onAttachedToWindow();        if (!mAttached) {            mAttached = true;            registerReceiver();           // .................略....................        }    }    @Override    protected void onDetachedFromWindow() {        super.onDetachedFromWindow();        if (mAttached) {            unregisterReceiver();           // .................略....................        }    }    private void registerReceiver() {        final IntentFilter filter = new IntentFilter();        filter.addAction(Intent.ACTION_TIME_TICK);        filter.addAction(Intent.ACTION_TIME_CHANGED);        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);        getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());    }    private void unregisterReceiver() {        getContext().unregisterReceiver(mIntentReceiver);    }    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            if (mTimeZone == null &&    Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {                final String timeZone = intent.getStringExtra("time-zone");                createTime(timeZone);            }            onTimeChanged();        }    };    private void onTimeChanged() {        mTime.setTimeInMillis(System.currentTimeMillis());        setText(DateFormat.format(mFormat, mTime));        setContentDescription(DateFormat.format(mDescFormat, mTime));    }

Space

效果图

实现原理

Space控件继承自View,在构造函数直接把控件设置为INVISIBLE模式,修改测量方法onMeasure,取消了draw方法的canvas绘制渲染的处理,下面是测量宽高相关核心代码

 private static int getDefaultSize2(int size, int measureSpec) {        int result = size;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        switch (specMode) {            case MeasureSpec.UNSPECIFIED:                result = size;                break;            case MeasureSpec.AT_MOST:                result = Math.min(size, specSize);                break;            case MeasureSpec.EXACTLY:                result = specSize;                break;        }        return result;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        setMeasuredDimension(                getDefaultSize2(getSuggestedMinimumWidth(), widthMeasureSpec),                getDefaultSize2(getSuggestedMinimumHeight(), heightMeasureSpec));    }

如果在以前你喜欢用View控件,setVisiblity占用屏幕空间,建议以后替换成Space控件,好处在于draw方法的重写,具体不解释。

ZoomButton 、ZoomControls

效果图

实现原理

ZoomButton内部就一个核心点,设置ZoomSpeed,默认速度值1000,ZoomControl是一个自定义的ViewGroup,布局控件默认inflater预先定义好的布局,如下

<merge xmlns:android="http://schemas.android.com/apk/res/android">    <ZoomButton android:id="@+id/zoomOut"         android:background="@android:drawable/btn_zoom_down"         android:layout_width="wrap_content"        android:layout_height="wrap_content"        />    <ZoomButton android:id="@+id/zoomIn"         android:background="@android:drawable/btn_zoom_up"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        />merge>

如果你想改变着丑陋的UI,你可以尝试拷贝源码出来,修改Inflater的布局即可。这个空间提供的show 、hide方法只是在执行透明动画,关键代码块如下

  public void show() {        fade(View.VISIBLE, 0.0f, 1.0f);    }    public void hide() {        fade(View.GONE, 1.0f, 0.0f);    }    private void fade(int visibility, float startAlpha, float endAlpha) {        AlphaAnimation anim = new AlphaAnimation(startAlpha, endAlpha);        anim.setDuration(500);        startAnimation(anim);        setVisibility(visibility);    }

该类对ZoomSpeed值提供了一个方法setZoomSpeed设置,其他的没什么好关注的,Listener的监听回调也略过吧,就这样吧。(merge没用过的可以去了解一下)

AdapterViewAnimator、AdapterViewFlipper、StackView

效果图

实现原理

AdapterViewFlipper可以实现轮播图片,虽然有点撇脚,不能手动滑动,也无法感知轮播到了那个界面,关于这一点可以重写控件,修改showNext回调位置,至于手动滑动需要手势拦截处理这块怎么说呢,你若有兴趣自己造轮子可以试试。

这里要区别两个类:ViewFlipper和AdapterViewFlipper,这是两个不同的类,下面是他们的继承体系

AdapterViewFlipper的自定义属性在他的父类有定义自己也有定义,下面来看看具体的含义与代码调用方法

下面是对照自定义属性的说明和方法调用

自定义属性 注释 对应方法
inAnimation 组件显示时用的动画 setInAnimation()
outAnimation 组件隐藏时用的动画 setInAnimation()
animateFirstView 组件显示第一个View时是否播放动画 setAnimateFirstView(),默认播放动画
loopViews 循环到最后一个视图是否回到第一个视图 AdapterViewFlipper强制设为了true
flipInterval 循环播放动画时间间隔 setFlipInterval()默认1000间隔
autoStart 是否自动播放动画 setAutoStart()

当你使用默认播放动画切换视图感觉不是1秒,不要觉得奇怪,动画执行也需要时间的,默认in 、out 动画时常都是200。对于代码功能性调用来说我们只需要关注下面这几个方法即可

startFlipping开启轮播没啥好说的,该类同样使用了上面提到的注册广播,注册了屏幕关闭和唤醒广播,关闭屏幕就暂停轮播,唤醒时如果之前是轮播状态,那么继续开始轮播。(相关代码块就不贴,自己查看源代码)

StackView虽说也是AdapterViewAnimator子类,但是其实现效果与AdapterViewFlipper不同,具体效果图就不贴了,实在是原生控件在实际得出的效果拿不出手,而且感觉在应用场景上来说也找不到对应的,于是乎在github检索了一会,找到了一个还算不错的开源,下面是地址和效果图:https://github.com/blipinsk/FlippableStackView

QuickContactBadge

这个ImageView的扩展可以简单的了解一下,推荐农民伯伯大神博客地址:http://www.cnblogs.com/over140/archive/2010/09/28/1837287.html,开发中用的比较少,大概看看就行了

ViewAnimator、ViewFlipper、ViewSwitcher、TextSwitcher

ViewFlipper、ViewSwitcher都是继承自ViewAnimator,ViewFlipper与AdapterViewFlipper差别不大略过,这里主要是关注一下ViewSwitcher相关类扩展一下视野。ViewAnimator是继承自FrameLayout,而ViewSwitcher是其子类,强制有且只能有2个childView,TextSwitcher限定childView必须是TextView.关于这类扩展控件自行检索Github.

Spinner、AbsSpinner、AdapterView、AutoCompleteTextView、MultiAutoCompleteTextView、ListPopupWindow、ListView到底有多亲密的关系?

直接贴代码估计比较晦涩难懂了,能把人给绕晕了,我们还是先看图说话吧。

他们之间的的关系到底有多深呢,且听我一一道来。最上层ViewGrou抽象下来的Adapter,拥有很多子类,Spinner的具体实现,跟踪源代码发现内部有实例化出一个ListPopuWindow、DialogPopup(根据不同的mode选择不同的实例,本质区别一个是popuwindow一个是AlertDialog),而ListPopuWindow类让我发现了这么个东西DropDownListView 的实例(AlertDialog同样调用了getLitView方法)

  private static class DropDownListView extends ListView {  }     

由此可以知道每个ListPopuWindow里面有一个LIstView,Spinner弹出来的其实就是ListView绑定适配器,而Spinner内部定义了一个DropDownAdapter,ListView绑定Adapter,最后调用各自mode对应的popu.show就可以了。那么问题来了,Spinner在很么时候弹出ListPopuWindow?带着这个问题继续跟踪Spinner源码

ViewGroup继承自View,所以可以共享父类方法performClick,点击时会调用该方法,自然Spinner也不例外,具体调用代码块如下(当然还有其他地方有触发,这里暂不深入理解了)

    @Override    public boolean performClick() {        boolean handled = super.performClick();        if (!handled) {            handled = true;            if (!mPopup.isShowing()) {                mPopup.show(getTextDirection(), getTextAlignment());            }        }        return handled;    }

用过的人都知道Spinner的Item预定义样式有点丑陋,主要是AbsSpinner搞鬼,下面是预定义的载入代码块(修改Spinner样式可以参考adapter这里的调用)

  public AbsSpinner(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);        initAbsSpinner();        final TypedArray a = context.obtainStyledAttributes(                attrs, R.styleable.AbsSpinner, defStyleAttr, defStyleRes);        final CharSequence[] entries = a.getTextArray(R.styleable.AbsSpinner_entries);        if (entries != null) {            final ArrayAdapter adapter = new ArrayAdapter(                    context, R.layout.simple_spinner_item, entries);            adapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);            setAdapter(adapter);        }        a.recycle();    }

看完Spinner有了个大概的认知,再看AutoCompleteTextView(他的子类同理略过了),内部同样实例了ListPopuWindow,添加了一个EditText输入内容的监听

   addTextChangedListener(new MyWatcher());

如果你对这个方法不陌生应该秒懂了吧,根据输入内容,当输入内容有变化立即执行过滤匹配适配器,这里过滤具体实现暂不涉及。

CheckedTextView

在之前我写过一篇关于ListView的单选和多选相关的分析的博客http://blog.csdn.net/analyzesystem/article/details/51319841,里面有提到一个非常重要的接口Checkable,这里就不多说废话了,同时提供一个开源库关于CheckedTextView相关的扩展库(别太当真,看看就好,扩展视野)
https://github.com/akbarsha03/Custom_CheckedTextView

Chronometer

这是一个扩展子TextView的计时器控件,然而我不得不吐槽,官方提供的很多原生控件都不咋样,与开源项目同类型的开源控件没法比,关于计时器这个,在很久以前貌似我也写了一篇blog分析一个计时器开源项目做了个纪录,地址:http://blog.csdn.net/analyzesystem/article/details/50435228


小结

收获了两点:

1.在onAttachedToWindow和onDetachedFromWindow方法注册广播和取消注册,接收到广播,来做一些回调或者更新UI
2.了解了Spinner AutoCompleteTextView ListView等相关类的相关实现。

更多相关文章

  1. Android(安卓)Hook神器:XPosed入门与登陆劫持演示
  2. android基本布局
  3. Android深入讲解WebView——下
  4. Android登陆页面软键盘弹起避免遮挡按钮实现
  5. android parcelable 详细介绍
  6. java解析json字符串的两种方法详解(Android通用)
  7. [置顶] Android:图解Activity启动流程源码(整体流程)
  8. Android(安卓)4.0.3 联系人(通讯录)应用源码学习
  9. View基础知识总结

随机推荐

  1. 【DB笔试面试759】在Oracle中,如果主库丢
  2. Oracle绑定变量分级(Bind Graduation)
  3. 【DB笔试面试719】在Oracle中,什么是OCR、
  4. Oracle结果集缓存(Result Cache)--服务器、
  5. 【DB笔试面试745】在Oracle中,RAC环境下的
  6. 【ASM】Oracle ASM + 11gR2 + RHEL6.5 安
  7. Oracle增量备份和快速备份(块改变跟踪Bloc
  8. Oracle收集统计信息
  9. Oracle 12c 新SQL提示(hint)
  10. Oracle的告警日志之v$diag_alert_ext视图