在上一篇《Android开发技巧——使用Dialog实现仿QQ的ActionSheet菜单》中,讲了这种菜单的实现过程,接下来将把它改成一个可复用的控件库。

本文原创,转载请注明出处:

http://blog.csdn.net/maosidiaoxian/article/details/46324941

对于要实现的可复用的控件库,我需要它具备以下两点:

  1. 可添加远程依赖(不考虑Eclipse中的使用)
  2. 可灵活配置

分离库的实现代码

对于第一点,需要做的就是在Android Studio中新建一个library的module,然后把相关的实现代码,资源分离出来拖过去,并且把library中如图标,一些字符串等没有用到的资源删掉,保持AndroidManifest.xml的干净(仅保留会用到的权限,声明等)。在这里,我们library的AndroidManifest最终只剩下了:

<manifest
    package="com.githang.android.actionsheet">

    <application/>

</manifest>

注意,application节点里 的allowBackup属性要去掉,不然会让一些不知道怎么用tools中的几个属性来解决冲突的人,面对AndroidManifest.xml的合并冲突不知所措。labelicon属性在这里也不需要,所以也去掉了。

然后把一开始创建的app module的包名加上.demo后缀,把com.githang.andorid.actionsheet仅作为我们的library的包名(这个是纯属个人习惯,你也可以不这么做。我是觉得在包名上把library和demo区分来比较好,而我又不想给library加多一个.library的包。

分离完之后的项目是这样的:

https://github.com/msdx/ActionSheet/commit/934b73bc3e2d1504c9b13e87649ce388c59f4613

分离之后,就可以把我们的库打包成aar,并上传到jcenter,让别人能以添加远程依赖的方式来使用了。如何发布到jcenter,可以见我这篇博客:《使用Gradle发布Android开源项目到JCenter》

但是现在,我们仅完成的最基本的工作,因为,你不能要求每个人对一个库的要求都和你完全一样,可能有些人的需求中,需要改一下UI上的一些属性什么的。所以接下来,我们需要让我们的库能够灵活配置。

可自由配置的属性

我们的大部分属性是定义在xml中的。要改动这些属性,方法主要有两种:

1. 在Java代码中提供一些View的UI上的接口,让第三方通过调用它来设置。

2. 布局文件中使用属性的引用,而不是直接使用它的值。

如果你写的是自定义控件(通过继承View),那么你可能还需要自定义一些属性,让别人在使用的时候可以在xml中添加。由于这里我们写的不是这类控件,不需要用到它,在这里就不赘述了。

继续说上面的两种方法。Android中,采用xml定义布局,就是想让布局代码与逻辑代码相分离,所以第一种方式我是尽量少用的(在需要动态设置,或者是在Java代码中设置更简单时使用,)。下面先说一下第二种的方式的实现过程。

我们在xml中定义到的控件有三个,一是ListView,二是Button,三是ListView的Item。所以首先,在values文件夹里新建一个attrs.xml的属性文件,在里面分别定义三个属性,formatreference。如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="ActionSheetList" format="reference"/>
    <attr name="ActionSheetCancel" format="reference"/>
    <attr name="ActionSheetItem" format="reference"/>
</resources>

接着,把之前写的布局文件改为使用?attr的方式声明属性。

menu_item.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@android:id/text1"
          style="?attr/ActionSheetItem" />

dialog_action_sheet.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <ListView
        android:id="@+id/menu_items"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="?attr/ActionSheetList"
        android:listSelector="@android:color/transparent"/>

    <Button
        android:id="@+id/menu_cancel"
        style="?attr/ActionSheetCancel"/>
</LinearLayout>

然后在我们的style中声明这几个属性的style:

    <style name="ActionSheetList">
        <item name="android:divider">#c9dddddd</item>
        <item name="android:dividerHeight">1px</item>
    </style>
    <style name="ActionSheetItem">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">45dp</item>
        <item name="android:textSize">18sp</item>
        <item name="android:gravity">center</item>
        <item name="android:textColor">@color/menu_text</item>
    </style>
    <style name="ActionSheetCancel" parent="ActionSheetItem">
        <item name="android:layout_marginTop">8dp</item>
        <item name="android:layout_marginBottom">8dp</item>
        <item name="android:background">@drawable/menu_item_single</item>
    </style>

注意,这里的style的名称并不要求与attr中声明的名称一致,这里我只是懒得想其他名字,真的。

这样做了之后,其他人在使用的时候,会需要多一个步骤:在他的styler中的AppTheme(具体视androidmanifest中指定的theme而定)节点中,需要添加以下几项:

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="ActionSheetList">@style/ActionSheetList</item>
        <item name="ActionSheetItem">@style/ActionSheetItem</item>
        <item name="ActionSheetCancel">@style/ActionSheetCancel</item>
    </style>

如果他想自己修改属性的值,只需要写对应的style,然后把上面的item里的值改为他写的style即可。

对于菜单的改动,我们就改到这里。

接下来是对ActionSheetDialog的重构,让它提供可以进行以下设置的API:

  • 设置显示与隐藏时的动画
  • 设置菜单的背景

首先是菜单的背景,上文已经说过它一共有四个背景。所以定义一个菜单背景的类:

    /**
     * 菜单背景
     */
    public static class MenuBackground {
        public int top;
        public int middle;
        public int bottom;
        public int single;

        public MenuBackground() {}

        public MenuBackground(int top, int middle, int bottom, int single) {
            this.top = top;
            this.middle = middle;
            this.bottom = bottom;
            this.single = single;
        }
    }

然后定义一个菜单背景的对象,给它初始值,并定义一个设置背景的方法:

    private MenuBackground mMenuBg = new MenuBackground(R.drawable.menu_item_top,
            R.drawable.menu_item_middle, R.drawable.menu_item_bottom, R.drawable.menu_item_single);

    public void setMenuBackground(int top, int middle, int bottom, int single) {
        mMenuBg.top = top;
        mMenuBg.middle = middle;
        mMenuBg.bottom = bottom;
        mMenuBg.single = single;
    }

最后剩下动画的配置的。定义分别设置显示及隐藏动画的两个方法,注意,对隐藏动画的方法中,要设置动画结束的回调,在这里隐藏我们的菜单。

动画设置的代码重构如下:

    private void initAnim(Context context) {
        setShowAnimation(AnimationUtils.loadAnimation(context, R.anim.translate_up));
        setDismissAnimation(AnimationUtils.loadAnimation(context, R.anim.translate_down));
    }

    /**
     * @param animation Showing animation.
     * @since 0.2
     */
    public void setShowAnimation(Animation animation) {
        mShowAnim = animation;
    }

    /**
     * @param animation Dismissing animation.
     * @since 0.2
     */
    public void setDismissAnimation(Animation animation) {
        mDismissAnim = animation;
        mDismissAnim.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                dismissMe();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
    }

现在我们的库已经重构完了,它暴露了适当的API,以让其他人可以自定义一些属性。它也对布局文件的配置提供了方法,即通过style来进行配置。

最后就是升版本号,改README,发布新版本了,打TAG了。

项目最后如下:

https://github.com/msdx/ActionSheet/tree/0.2

Android开发技巧——实现可复用的ActionSheet菜单的更多相关文章

  1. Android开发技巧——使用PopupWindow实现弹出菜单

    在本文当中,我将会与大家分享一个封装了PopupWindow实现弹出菜单的类,并说明它的实现与使用. 因对界面的需求,android原生的弹出菜单已不能满足我们的需求,自定义菜单成了我们的唯一选择,在 ...

  2. Android开发技巧——自定义控件之使用style

    Android开发技巧--自定义控件之使用style 回顾 在上一篇<Android开发技巧--自定义控件之自定义属性>中,我讲到了如何定义属性以及在自定义控件中获取这些属性的值,也提到了 ...

  3. Android开发技巧——自定义控件之自定义属性

    Android开发技巧--自定义控件之自定义属性 掌握自定义控件是很重要的,因为通过自定义控件,能够:解决UI问题,优化布局性能,简化布局代码. 上一篇讲了如何通过xml把几个控件组织起来,并继承某个 ...

  4. 50个android开发技巧

    50个android开发技巧 http://blog.csdn.net/column/details/androidhacks.html

  5. Android开发技巧——大图裁剪

    本篇内容是接上篇<Android开发技巧--定制仿微信图片裁剪控件> 的,先简单介绍对上篇所封装的裁剪控件的使用,再详细说明如何使用它进行大图裁剪,包括对旋转图片的裁剪. 裁剪控件的简单使 ...

  6. Android开发技巧——高亮的用户操作指南

    Android开发技巧--高亮的用户操作指南 2015-12-15补记: 发现使用PopupWindow进行遮罩层的显示,在华为P7上会有问题.具体表现为:画出来的高亮部分会偏下.原因为:通过view ...

  7. Android开发技巧——自定义控件之增加状态

    Android开发技巧--自定义控件之增加状态 题外话 这篇本该是上周四或上周五写的,无奈太久没写博客,前几段把我的兴头都用完了,就一拖再拖,直到今天.不想把这篇拖到下个月,所以还是先硬着头皮写了. ...

  8. Android开发技巧——自定义控件之组合控件

    Android开发技巧--自定义控件之组合控件 我准备在接下来一段时间,写一系列有关Android自定义控件的博客,包括如何进行各种自定义,并分享一下我所知道的其中的技巧,注意点等. 还是那句老话,尽 ...

  9. Android开发技巧——写一个StepView

    在我们的应用开发中,有些业务流程会涉及到多个步骤,或者是多个状态的转化,因此,会需要有相关的设计来展示该业务流程.比如<停车王>应用里的添加车牌的步骤. 通常,我们会把这类控件称为&quo ...

随机推荐

  1. JBOSS EAP6 系列二 客户端访问位于EAR中的EJB时,jndi name要遵守的规则

    EJB 的 jndi语法(在整个调用远程ejb的过程中语法的遵循是相当重要的) 参见jboss-as-quickstarts-7.1.1.CR2\ejb-remote\client\src\main\ ...

  2. 使用Java正则表达式去掉Double类型的数据后面多余的0

    方法 /** * 使用java正则表达式去掉多余的.与0 * @param s * @return */ public static String subZeroAndDot(String s){ i ...

  3. How to generate the complex data regularly to Ministry of Transport of P.R.C by DB Query Analyzer

    How to generate the complex data regularly to Ministry of Transport of P.R.C by DB Query Analyzer 1 ...

  4. 【翻译】Ext JS 6.2 早期访问版本发布

    原文:Announcing Ext JS 6.2 Early Access 非常开心,Sencha Ext JS 6.2早期访问版本今天发布了.早期访问版本的主要目的是为了让大家进行测试并评估Ext ...

  5. 1、Android测试入门

    编写和运行测试时Android APP开发周期中的重要的一环.好的测试可以让你非常容易的在开发过程中发现bug,提升你对自己代码的自信.使用Android Studio,你可以在物理设备或者虚拟机中运 ...

  6. Fetch XML and ConditionExpression operators

    https://msdynamicscrmblog.wordpress.com/2013/05/10/fetch-xml-and-conditionexpression-operators-using ...

  7. Linux下多线程编程遇到的一些问题

    今天在学习了Linux的多线程编程的基础的知识点.于是就试着做了一个简单的Demo.本以为会得到预期的结果.不成想却遇到了意想不到的问题. 代码展示 我的C 代码很简单,就是一个简单的示例程序,如下: ...

  8. hive的map类型处理

    https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF#LanguageManualUDF-CollectionFunc ...

  9. Android反编译获取源码-android学习之旅(70)

    上一讲我们介绍了如何获取资源文件,这一节讲解如何获取源码,其实获取源码真的很简单 首先还是要有工具,Dex2jar,这个工具用于将apk解压之后的dex文件转化为jar文件还有jd-gui的这个工具能 ...

  10. Leetcode_119_Pascal's Triangle II

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/41851069 Given an index k, retu ...