2048游戏回顾三:自定义Dialog和ProgressBar

在2048游戏中,询问用户是否退出游戏,游戏失败或者成功后弹出对话框让用户做下一步选择,总之Dialog是必须要用的,但是系统默认的Dialog和游戏的UI风格不搭,因此要求我们必须自定义Dialog.ProgressBar主要用在游戏启动的时候显示游戏的加载进度,也是游戏必不可有的部分,也需要自定义。

Dialog的自定义

Dialog的自定义是非常简单的事情,为了更好的理解Dialog的工作机理,学习一下WindowManger类的作用是有必要的。

WindowManger

WindowManager在Android的窗口管理机制中占有核心的地位,为什么这么说呢,这个类有些方法,可以直接添加一个View,也可以删除一个View,典型的说就是悬浮窗,悬浮窗的实现就是使用WindowManager类的,悬浮窗具体的使用可以参考我的这篇文章:Android悬浮窗使用总结
简单的说,我们可以把一个Button添加到界面上来,也可以把更加复杂的东西添加到界面上来。那么Dialog是不也是这么实现的呢?我的理解是是的(如果不对请拍砖),他们本质上都是使用WindowManager的addView方法来向界面添加View的,理解了这个,那我们很容易理解怎么自定义Dialog了,其实就是自己构建好一个View,在通过Dialog中封装好的一些方法,最终还是使用WindowManager的addView方法来向系统添加View.

实现步骤

自定义Dialog的步骤简要的可以总结为两步:
1.创建View或者布局文件
2.添加
在我的2048游戏中,askDialog的布局文件非常简单,如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="@drawable/bg_round_rectangle_white_stroke"
    android:layout_width="@dimen/ask_dialog_width"
    android:layout_height="@dimen/ask_dialog_height">
    <ImageView
        android:background="@drawable/bg_default_button_edge_top"
        android:src="@mipmap/game_name"
        android:layout_margin="5dp"
        android:id="@+id/header_image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <ImageView
        android:id="@+id/header_line"
        android:layout_below="@+id/header_image"
        android:background="@android:color/white"
        android:layout_width="match_parent"
        android:layout_height="2dp" />
    <TextView
        android:id="@+id/ask_text"
        android:gravity="center"
        android:textSize="@dimen/text_mode_size"
        android:textColor="@android:color/holo_blue_light"
        android:layout_below="@id/header_line"
        android:layout_centerHorizontal="true"
        android:text="@string/allow_go_back_ask"
        android:layout_width="wrap_content"
        android:layout_height="100dp" />
    <Button
        style="@style/dialog_button"
        android:text="@string/allow_go_back"
        android:id="@+id/dialog_button_yes"
        android:layout_below="@+id/ask_text"
        android:layout_marginLeft="20dp"
        android:layout_width="90dp"
        android:layout_height="40dp" />
    <Button
        style="@style/dialog_button"
        android:text="@string/forbid_go_back"
        android:id="@+id/dialog_button_no"
        android:layout_below="@+id/ask_text"
        android:layout_marginRight="20dp"
        android:layout_alignParentRight="true"
        android:layout_width="90dp"
        android:layout_height="40dp" />
</RelativeLayout>

很少有人会有耐心看这些code,之间看下它的效果吧:
这里写图片描述
现在我们把布局文件构造好了,现在我们需要添加到界面上来:

   private Dialog buildAskDialog(){
        Activity activity = getActivity();
        final Dialog askDialog = new Dialog(activity,R.style.CustomDialog);
        askDialog.setContentView(R.layout.ask_dialog_layout);
        Button button;
        button = (Button) askDialog.findViewById(R.id.dialog_button_yes);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Game2048StaticControl.isGoBackEnabled = true;
                goGameMainActivity();
                if(askDialog != null){
                    askDialog.dismiss();
                }
            }
        });
        button = (Button) askDialog.findViewById(R.id.dialog_button_no);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Game2048StaticControl.isGoBackEnabled = false;
                goGameMainActivity();
                if(askDialog != null){
                    askDialog.dismiss();
                }
            }
        });
        return askDialog;
    }

我们想系统添加了我们的View,当然是用的是布局文件。核心代码是:

        final Dialog askDialog = new Dialog(activity,R.style.CustomDialog);
        askDialog.setContentView(R.layout.ask_dialog_layout);

创建一个对话框,使用Dialog的setContentView方法添加。添加好了一号我们还需要给其中的一个view设置时间监听器,当然我们需要先获得它的实例,使用的是Dialog的findViewByID方法:

askDialog.findViewById(R.id.dialog_button_yes);

设置完这些以后,调用Dialog的show方法就可以显示出来Dialog了,是不是很简单?

自定义Dialog样式

Dialog是显示出来了,可以,这个时候Dialog的背景是白色的,并不是我们想要的透明的,怎么办呢?我们可以设置透明的主题:
比如在这款游戏中创建Dialog的代码如下:

Dialog(activity,R.style.CustomDialog);

可见我们给它传入了一个R.style.CustomDialog的自定义样式:

    <style name="CustomDialog" parent="android:style/Theme.Dialog">
        <!--背景颜色及透明程度-->
        <item name="android:windowBackground">@android:color/transparent</item>
        <!--是否有标题 -->
        <item name="android:windowNoTitle">true</item>
        <!--是否浮现在activity之上-->
        <item name="android:windowIsFloating">true</item>
        <!--是否模糊-->
        <item name="android:backgroundDimEnabled">false</item>
    </style>

具体的配置项注释中已经说的很清楚了。

Drawable

此外,我还想补充一点另外的知识,就是Dialog的背景,他是一个ShapeDrawable,Drawable在Android UI开发中真的用的特别的多,如果对它不熟悉,建议下点功夫把它彻底搞定。2048游戏中的Dialog的ShapeDrawable第一如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="12dp" />
    <solid android:color="@color/half_transparency_wihte"/>
    <stroke android:color="@android:color/white"
        android:width="5dp" />
</shape>

具体就不展开了大家可以自行去学习,此外Dialog中的Button的background也是使用了Drawable,叫做StateListDrawable,其定义如下:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true"
        android:drawable="@drawable/bg_button_dialog_focus" /> <!-- focused -->
    <item android:state_pressed="true"
        android:drawable="@drawable/bg_button_dialog_focus" /> <!-- hovered -->
    <item android:state_focused="false"
        android:drawable="@drawable/bg_button_dialog_default" /> <!-- default -->
</selector>

里面涉及到了forcus,pressed和unforcus三种状态,pressed状态和forcus状态使用的drawable一样的,确定以如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="5dp" />
    <solid android:color="@android:color/holo_blue_light"/>
</shape>

就是一个最简单的圆角矩形。
unforcus状态对应的drawable如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="5dp" />
    <solid android:color="@android:color/darker_gray"/>
</shape>

只是颜色不同而已。
Dialog的自定义就说到这里。

ProgressBar的自定义

ProgressBar的自定义本人研究也不深,就不班门弄斧了,简单的介绍下在这款游戏中对ProgressBar的自定义吧。
先从ProgressBar的使用说起,我们在xml中如此使用:

    <ProgressBar
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_below="@+id/frame_layout_container"
        android:indeterminateDrawable="@drawable/progress_self_define"
        android:layout_marginTop="20dp"
        android:indeterminate="true"
        android:indeterminateBehavior="repeat"
        android:layout_centerHorizontal="true"
        android:layout_width="500dp"
        android:layout_height="10dp" />

android:indeterminate=”true”是的这个ProgressBar永久循环,永久循环的ProgressBar的自定义样式使用的是android:indeterminateDrawable=”@drawable/progress_self_define”。因此,可以想象,如果你使用的不是永久循环的ProgressBar,自定义的drawable应该设置到android:progressDrawable=”“。其他的条目就不啰嗦了,下面看一下这款游戏中使用的样式:android:indeterminateDrawable

“`

<item android:id="@android:id/background">
    <shape android:shape="rectangle">
        <corners android:radius="5dip" />
        <solid android:color="@android:color/darker_gray"/>
    </shape>
</item>
<item android:id="@android:id/secondaryProgress">
    <clip>
        <shape>
            <corners android:radius="5dip" />
            <solid android:color="@android:color/holo_green_light"/>
        </shape>
    </clip>
</item>
<item android:id="@android:id/progress">
    <clip>
        <shape>
            <corners android:radius="5dip" />
            <solid android:color="@android:color/holo_orange_light"/>
        </shape>
    </clip>
</item>



background配置背景,progress配置进度条,secondaryProgress配置第二进度条。最终的结果如下:
这里写图片描述
此外,循环的ProgressBar还可以使用帧动画:animation-list来实现自定义,这种方式更好一点,以后可能会改为这种方式。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值