Android学习笔记_点九绘图与软键盘和事件传递

最近项目里遇到的几个小问题,以前只是用吗没有深入看过,现在总结到一起,防止以后这种小问题占用太多时间。还是通过网上别人总结的很多博客学习了,挑选出最易懂明了的。

还有leader很小的问题都不放过,亲自track代码,每个小现象的流程都搞得很清楚,追求完美不马虎,怪不得技术这么好,大方向架构小方向细节,这两方面都很认真,值得我学习。

1. 关于切图中的.9图片:

安卓android APP切图规范和.9png制作教程

这个跟上一篇差不多:关于”点九”

2. canvas绘图的:

PorterDuffXfermode的用法

setXfermode属性

下面会给出一个将bitmap截取为圆形图片的方法,背景黑色透明argb(0,0,0,0),无色。

    /**
     * 将图像处理为背景透明的圆形头像
     * @param bitmap
     * @return output
     */
    public static Bitmap toRoundBitmap(Bitmap bitmap) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        float roundPx;
        float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom;
        if (width <= height) {
            roundPx = width / 2;
            top = 0;
            bottom = width;
            left = 0;
            right = width;
            height = width;
            dst_left = 0;
            dst_top = 0;
            dst_right = width;
            dst_bottom = width;
        }
        else {
            roundPx = height / 2;
            float clip = (width - height) / 2;
            left = clip;
            right = width - clip;
            top = 0;
            bottom = height;
            width = height;
            dst_left = 0;
            dst_top = 0;
            dst_right = height;
            dst_bottom = height;
        }

        Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect src = new Rect((int) left, (int) top, (int) right, (int) bottom);
        final Rect dst = new Rect((int) dst_left, (int) dst_top, (int) dst_right, (int) dst_bottom);
        final RectF rectF = new RectF(dst);

        paint.setAntiAlias(true);

        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, src, dst, paint);
        return output;
    }
View Code

3. 焦点获取与软键盘:

起因:用了第三方Emoticon的输入法,用户发的帖子详情有评论功能,输入栏在屏幕底部,点击后会弹出键盘,笑脸是表情输入键盘和文字软键盘的切换。问题有两个:

Q1:点击某个跟帖进行评论时,焦点明明设置到评论输入栏了,键盘也出来了,可光标就是不在评论EditText上,能看到一闪而过的光标。

A1:因为表情隐藏在软键盘后,键盘显示的同时它的初始化会使里面的某个表情控件获取焦点,所以即使设置了评论输入栏的获取焦点事件,还是在键盘弹出时被后面Emoticon表情布局拿走了焦点。解决方法:延迟一定的时间再获取一次焦点,这个时间留给表情栏初始化,再次获取焦点就可以了。具体代码

    /**
     * <pre>
     * 显示回复评论框
     * </pre>
     */
    private void showDiscuss() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                mEmoticonsKeyBoard.changeEditTextFocus(true);
            }
        }, 500);
        mEmoticonsKeyBoard.changeEditTextFocus(true);
        // 显示键盘
        EmoticonsUtils.openSoftKeyboard(mEmoticonsKeyBoard.getContentEdit());
    }
View Code

 测试是偶尔获取不到,跟时间设置有关,可以长一点是500ms。

Q2:键盘弹出时,点击返回键软键盘先消失,表情键盘还没消失,需要再点击一次才可以收起。当用第三方输入法则点击一次返回就可以,而系统输入法就不可以。

A2:第三方Emoticon的输入栏其实监听了KEYEVENT_BACK,但是没有被传递到这个事件。认为是系统键盘拦截了这个事件把自己隐藏了就没有向下传递导致的。非系统键盘比如搜狗,可能自己重写的这个部分所以没啥事。解决思路是:监听软键盘的收起,在某个监听函数里隐藏表情键盘。leader提示软键盘收起时会引起View的重绘,此时有个函数被触发,可以在这里做文章。百度:

关于系统软键盘弹出隐藏监听的讨论

这篇里提到的方法便是了,解决中...

 事实上,表情输入法里有这个ResizeLayout,表情栏就是基于这个布局做的,仔细看了EmoticonsKeyBoardBar的代码,发现它继承自AutoHeightLayout,而AutoHeightLayout又继承自ResizeLayout。所以是带着OnResizeListener的接口的,只不过在EmoticonsKeyBoardBar中这个接口被包装成了KeyBoardBarViewListener,所以只要在这个监听接口中做文章就好了。棘手的是状态比较复杂。这个接口里有

public void OnKeyBoardStateChange(int state, int height);

state是EmoticonsKeyBoardBar用来记录表情键盘状态:

    public static final int KEYBOARD_STATE_NONE = 100;// 键盘隐藏
    public static final int KEYBOARD_STATE_FUNC = 102;// 表情栏显示,输入法软键盘消失
    public static final int KEYBOARD_STATE_BOTH = 103;// 表情栏隐藏在后面,输入法软键盘出现

height表示表情键盘高度。这样要想在103的状态时点击返回达到双键盘隐藏的效果,必须要保证两个连续条件:条件1,当前是双键盘显示状态,条件2,接着点击返回键。此时点击后隐藏双键盘。除此之外其他都按原来的操作。用OnKeyBoardStateChange监听条件1,发生后state=103,height=540;监听条件2,发生后state=102,height=0;因此,这俩个按顺序发生就让键盘整个隐藏就好了。mEmoticonsKeyBoard.hideAutoView();其余情况不处理。

贴一下这个监听接口的代码

 1 private boolean isHide = false;// 判断是否该隐藏全键盘
 2 mEmoticonsKeyBoard.setOnKeyBoardBarViewListener(new EmoticonsKeyBoardBar.KeyBoardBarViewListener() {
 3             @Override
 4             public void OnKeyBoardStateChange(int state, int height) {
 5                 // step1:state = 103, height = 540>0 时,双键盘显示
 6                 if (state == 103 && height > 0) {
 7                     isHide = true;
 8                 }
 9                 //  step2:双键盘显示时,点击返回键收起两个键盘
10                 if(isHide && state == 102 && height == 0){
11                     mEmoticonsKeyBoard.hideAutoView();
12                     //isHide = false;
13                 }
14                 // 非上述两种前后组合时,均不做操作
15                 if (!(state == 103 && height > 0)) {
16                     isHide = false;
17                 }
18 
19             }
20 
21             @Override
22             public void OnSendBtnClick(String msg) {
23                 MobclickAgent.onEvent(MomentDetailActivity.this, "click_89");
24                 mEmoticonsKeyBoard.resetFaceBtn();
25                 // 隐藏键盘
26                 mEmoticonsKeyBoard.hideAutoView();
27                 clickCommentPublish(msg);
28             }
29         });
View Code

 

4. 上面键盘事件没有拦截到返回键点击,是跟android的事件传递机制有关的。学了这篇帖子之后,感觉:还是要好好看源码解决问题啊。

Android事件传递机制

 

 

posted @ 2015-09-03 12:06  Matrix_Ran  阅读(442)  评论(0编辑  收藏  举报