此文接着《Android快速自定义控件+实战演示(二)组合自定义view+回调》继续讲解。

这一节会提供的知识点:
1.如何把之前做好的单一控件组合成一个完整的键盘控件
2.如何在新的键盘控件里进行回调操作,使得能够选中点击某个数字/字母时,进行相关操作(比如打印出来)

回顾一下项目目标

我们要实现一种用在机顶盒端的自定义键盘,效果图如下

在上一节,我们已经实现了单个自定义按键的切换,现在就是通过布局,把它们排列成九宫格(如果包括最下面一行应该是十二宫格)就可以了。

自定义键盘

看了前两节教程,现在是不是觉得自定义控件超简单的。

自定义布局

首先取名custom_keyboard.xml,因为按键与按键之间有重叠的部分(所有按键都以圆盘形式展开的话,可发现有重叠),我用了RelativeLayout,所以自定义view的时候继承RelativeLayout。

自定义View类

新建一个类,名为CustomKeyboard.java继承RelativeLayout。
依旧在所有构造方法里加上我们的新方法load(),在load()方法里初始化布局(inflateLayout()),UI(initUI())和数据(initData())。
在布局里引入custom_keyboard.xml

    /** * @Description inflate the main layout */    private void inflateLayout() {        try {            LayoutInflater.from(getContext()).inflate(R.layout.custom_keyboard, this, true);        } catch (Exception e) {            e.printStackTrace();        }    }

initUI()里将所有的按键获取到,包括清空和删除按钮。

    /** * @Description initialize the ui */    private void initUI() {        mItem1 = (CustomNumKeyboardItem) findViewById(R.id.item1); //数字1只用了数字按键,而不是组合按键,因为数字1下面没有字母,所以也不会出现圆盘按键        mItem2 = (CustomKeyboardItem) findViewById(R.id.item2);        mItem3 = (CustomKeyboardItem) findViewById(R.id.item3);        mItem4 = (CustomKeyboardItem) findViewById(R.id.item4);        mItem5 = (CustomKeyboardItem) findViewById(R.id.item5);        mItem6 = (CustomKeyboardItem) findViewById(R.id.item6);        mItem7 = (CustomKeyboardItem) findViewById(R.id.item7);        mItem8 = (CustomKeyboardItem) findViewById(R.id.item8);        mItem9 = (CustomKeyboardItem) findViewById(R.id.item9);        //最后一行没有使用自定义view        mItem0 = (Button) findViewById(R.id.item0);        mItemClear = (ImageButton) findViewById(R.id.itemClear);        mItemDelete = (ImageButton) findViewById(R.id.itemDelete);    }

因为键盘的ABC…以及数字排列都是固定的,我们把数据以数组的格式存在custom_keyboard_arrays.xml里面

<?xml version="1.0" encoding="utf-8"?><resources>    <string-array name="item1">        <item>"1"</item>    </string-array>    <string-array name="item2">        <item>"2"</item>        <item>"A"</item>        <item>"B"</item>        <item>"C"</item>    </string-array>    <string-array name="item3">        <item>"3"</item>        <item>"D"</item>        <item>"E"</item>        <item>"F"</item>    </string-array>    <string-array name="item4">        <item>"4"</item>        <item>"G"</item>        <item>"H"</item>        <item>"I"</item>    </string-array>    <string-array name="item5">        <item>"5"</item>        <item>"J"</item>        <item>"K"</item>        <item>"L"</item>    </string-array>    <string-array name="item6">        <item>"6"</item>        <item>"M"</item>        <item>"N"</item>        <item>"O"</item>    </string-array>    <string-array name="item7">        <item>"7"</item>        <item>"P"</item>        <item>"Q"</item>        <item>"R"</item>        <item>"S"</item>    </string-array>    <string-array name="item8">        <item>"8"</item>        <item>"T"</item>        <item>"U"</item>        <item>"V"</item>    </string-array>    <string-array name="item9">        <item>"9"</item>        <item>"W"</item>        <item>"X"</item>        <item>"Y"</item>        <item>"Z"</item>    </string-array></resources>

然后在设置数据的时候,一一对应。

    /** * @Description initialize the data */    private void initData() {        String[] dataItem1 = getResources().getStringArray(R.array.item1);        String[] dataItem2 = getResources().getStringArray(R.array.item2);        String[] dataItem3 = getResources().getStringArray(R.array.item3);        String[] dataItem4 = getResources().getStringArray(R.array.item4);        String[] dataItem5 = getResources().getStringArray(R.array.item5);        String[] dataItem6 = getResources().getStringArray(R.array.item6);        String[] dataItem7 = getResources().getStringArray(R.array.item7);        String[] dataItem8 = getResources().getStringArray(R.array.item8);        String[] dataItem9 = getResources().getStringArray(R.array.item9);        CustomKeyboardItemEntity cEntity = new CustomKeyboardItemEntity(                dataItem1[0], "", "", ""); //数字1下面没有字母        mItem1.setData(cEntity);        cEntity = new CustomKeyboardItemEntity(                dataItem2[0], dataItem2[1], dataItem2[2], dataItem2[3]);        mItem2.setData(cEntity);        cEntity = new CustomKeyboardItemEntity(                dataItem3[0], dataItem3[1], dataItem3[2], dataItem3[3]);        mItem3.setData(cEntity);        cEntity = new CustomKeyboardItemEntity(                dataItem4[0], dataItem4[1], dataItem4[2], dataItem4[3]);        mItem4.setData(cEntity);        cEntity = new CustomKeyboardItemEntity(                dataItem5[0], dataItem5[1], dataItem5[2], dataItem5[3]);        mItem5.setData(cEntity);        cEntity = new CustomKeyboardItemEntity(                dataItem6[0], dataItem6[1], dataItem6[2], dataItem6[3]);        mItem6.setData(cEntity);        cEntity = new CustomKeyboardItemEntity(                dataItem7[0], dataItem7[1], dataItem7[2], dataItem7[3], dataItem7[4]);        mItem7.setData(cEntity);        cEntity = new CustomKeyboardItemEntity(                dataItem8[0], dataItem8[1], dataItem8[2], dataItem8[3]);        mItem8.setData(cEntity);        cEntity = new CustomKeyboardItemEntity(                dataItem9[0], dataItem9[1], dataItem9[2], dataItem9[3], dataItem9[4]);        mItem9.setData(cEntity);    }

这一段我个人都觉得看得非常冗余,要是能优化一下,弄成一个循环就好了!(如果你有好的想法,欢迎提出来哦!)

运行,基本界面就出来了。

监听按键响应事件(组合回调)

响应的事件比如字母、数字按OK键就打印相应字符,删除和清除按OK键就删除一个字符或者清空所有字符。

分析:点击某个按键的时候,数字按键会先变成圆盘按键,然后圆盘按键点击OK键,能够监听点击并得到当前选中的字符;而现在自定义键盘或者更外层,需要能够继续处理该点击事件。故得到当前字符写在圆盘按键类里,并通过回调传值给自定义键盘类,且自定义键盘类能够继续处理点击事件。

下面我用代码来解释说明。

先定义一个监听器类OnDpadCenterListener,定义三个方法分别响应点击字符、删除和清除事件。其中字符要传值给代理(实现者)。

/** * @ClassName OnDpadCenterListener * @Description 按中键的监听器 * @author azz * @Date 2015年6月15日 下午6:23:55 * @version 1.0.0 */public interface OnDpadCenterListener {    /** * @Description 按中心键的时候 * @param selectString 选中的字符 */    void onDpadCenter(String selectString);    /** * @Description 清除按钮被点击 */    void onClearPressed();    /** * @Description 当删除按钮被点击 */    void onDeletePressed();}

然后,本来的思路应该是,我们接着在圆盘按键类里面的onKey事件里面的分类KEYCODE_DPAD_CENTER里加上如果本类的属性mOnDpadCenterListener 不为 null,就调用onDpadCenter(getSelectedString(())

但其实我发现,我之前写过一个OnKeyWorkListener,是用来供组合自定义按键回调的,监听了数字按键的OK键和圆盘按键的Back键,而圆盘按键类(CustomCircleKeyboardItem)本身已经有了这个监听器属性,原来只监听了Back键,现在我们就可以加上监听OK键:

    public boolean onKey(final View v, final int keyCode, final KeyEvent event) {        if (event.getAction() == KeyEvent.ACTION_DOWN) {            switch (keyCode) {            //...            case KeyEvent.KEYCODE_DPAD_CENTER:                if (mOnKeyWorkListener != null) {                    mOnKeyWorkListener.onDpadCenter(this);                }                break;            //...            }            updateDataBackup();        }        //...    }

然后在组合按键(CustomKeyboardItem)里加上新属性

    /** * @Field @onDpadCenterListener : 监听中键 */    private OnDpadCenterListener mOnDpadCenterListener;

并且在onDpadCenter(View view)方法里加上新的判断if (view == circleKeyboardItem)如果是圆盘按键被点击OK键,就传给mOnDpadCenterListener去处理:

    @Override    public void onDpadCenter(final View view) {        Log.d(TAG, "onDpadCenter");        if (view == numKeyboardItem                && numKeyboardItem.isShown()                && !circleKeyboardItem.isShown()) {            circleKeyboardItem.appearWithAnimation(showAnim);            numKeyboardItem.disappearWithAnimation(showAnim);        } else if (view == circleKeyboardItem) { //新加入的判断            if (null != mOnDpadCenterListener) {                mOnDpadCenterListener.onDpadCenter(circleKeyboardItem.getSelectedString());            }        }    }

好了,该写的都写好了,现在只要在哪写好OnDpadCenterListener传进来就可以了。

我同样给了CustomKeyboard类一个OnDpadCenterListener属性,让外层将实现传给CustomKeyboard,再由CustomKeyboard分发给它的子控件。

    /** * @param onDpadCenterListener the onDpadCenterListener to set */    public void setOnDpadCenterListener(final OnDpadCenterListener onDpadCenterListener) {        this.mOnDpadCenterListener = onDpadCenterListener;        mItem1.setOnDpadCenterListener(mOnDpadCenterListener);        mItem2.setOnDpadCenterListener(mOnDpadCenterListener);        mItem3.setOnDpadCenterListener(mOnDpadCenterListener);        mItem4.setOnDpadCenterListener(mOnDpadCenterListener);        mItem5.setOnDpadCenterListener(mOnDpadCenterListener);        mItem6.setOnDpadCenterListener(mOnDpadCenterListener);        mItem7.setOnDpadCenterListener(mOnDpadCenterListener);        mItem8.setOnDpadCenterListener(mOnDpadCenterListener);        mItem9.setOnDpadCenterListener(mOnDpadCenterListener);        mItem0.setOnClickListener(new OnClickListener() {            @Override            public void onClick(final View v) {                if (null != mOnDpadCenterListener) {                    mOnDpadCenterListener.onDpadCenter(mItem0.getText().toString());                }            }        });        mItemClear.setOnClickListener(new OnClickListener() {            @Override            public void onClick(final View v) {                if (null != mOnDpadCenterListener) {                    mOnDpadCenterListener.onClearPressed();                }            }        });        mItemDelete.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                if (null != mOnDpadCenterListener) {                    mOnDpadCenterListener.onDeletePressed();                }            }        });    }

当其他地方(比如MainActivity)传入监听器OnDpadCenterListener的实现,就可以响应响应按键了。

如果你有任何问题,欢迎留言告诉我。

更多相关文章

  1. Android(安卓)手势操作GestureDetector
  2. Android监听事件的回调机制
  3. Android(安卓)UI设计之自定义Dialog,实现各种风格效果的对话框
  4. Android快速自定义控件+实战演示(二)组合自定义view+回调
  5. android 验证码输入框
  6. Android(安卓)监听系统媒体音量变化
  7. Android(安卓)-- ListView(SimpleAdapter) 自定义适配器
  8. Android开发-DesignDemo-AndroidStudio(五)Coordinator
  9. android问题:保存文件后文件内容为空

随机推荐

  1. m2e-android (一个集成ADT和 Maven Androi
  2. android中的定时任务AlarmManager
  3. [Android] Android打开WIFI或者移动网络
  4. Android(安卓)五大布局之(一) 线性布局和相
  5. android make-standalone-toolchain.sh
  6. android监听音量上下键调节音量
  7. Android情景模式、文件管理器 完整示例编
  8. [Android] Ignoring InnerClasses attrib
  9. Android(安卓)解析XML
  10. How To: Install Flash 10.1 On Android(