Android實現QQ換頭像的對話框

之前一直覺得QQ換頭像彈出的對話框挺好看的,而且在項目中也有這個
需求,於是寫一個Demo出來分享一下。

話不多說,先來張效果圖看看。
QQ換頭像對話框

上面是QQ中的效果。

Demo效果

上面的效果圖爲需要實現的效果。

簡單來說,就是彈出了一個對話框。接下來說說是怎麼實現的。

對話框Dialog中的是自定義View,下面先貼出代碼head_dialog。

<?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:gravity="bottom"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_take_dy_photo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/dialog_margin"
        android:layout_marginRight="@dimen/dialog_margin"
        android:background="@drawable/selector_top_round"
        android:gravity="center"
        android:padding="@dimen/dialog_padding"
        android:text="@string/take_dy_photo"
        android:textColor="@color/colorPrimary"
        android:textSize="@dimen/text_size_16" />

    <View
        android:layout_width="match_parent"
        android:layout_height="@dimen/cut_view_height"
        android:layout_marginLeft="@dimen/dialog_margin"
        android:layout_marginRight="@dimen/dialog_margin"
        android:background="@color/grey" />

    <TextView
        android:id="@+id/tv_select_photo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/dialog_margin"
        android:layout_marginRight="@dimen/dialog_margin"
        android:background="@drawable/selector_none_round"
        android:gravity="center"
        android:padding="@dimen/dialog_padding"
        android:text="@string/select_photo"
        android:textColor="@color/colorPrimary"
        android:textSize="@dimen/text_size_16" />

    <View
        android:layout_width="match_parent"
        android:layout_height="@dimen/cut_view_height"
        android:layout_marginLeft="@dimen/dialog_margin"
        android:layout_marginRight="@dimen/dialog_margin"
        android:background="@color/grey" />

    <TextView
        android:id="@+id/tv_take_photo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/dialog_margin"
        android:layout_marginRight="@dimen/dialog_margin"
        android:background="@drawable/selector_none_round"
        android:gravity="center"
        android:padding="@dimen/dialog_padding"
        android:text="@string/take_photo"
        android:textColor="@color/colorPrimary"
        android:textSize="@dimen/text_size_16" />

    <View
        android:layout_width="match_parent"
        android:layout_height="@dimen/cut_view_height"
        android:layout_marginLeft="@dimen/dialog_margin"
        android:layout_marginRight="@dimen/dialog_margin"
        android:background="@color/grey" />

    <TextView
        android:id="@+id/tv_look_big_pic"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/dialog_margin"
        android:layout_marginRight="@dimen/dialog_margin"
        android:background="@drawable/selector_bottom_round"
        android:gravity="center"
        android:padding="@dimen/dialog_padding"
        android:text="@string/look_big_pic"
        android:textColor="@color/colorPrimary"
        android:textSize="@dimen/text_size_16" />

    <TextView
        android:id="@+id/tv_cancel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/dialog_margin"
        android:background="@drawable/selector_all_round"
        android:gravity="center"
        android:padding="@dimen/dialog_padding"
        android:text="@string/cancel"
        android:textColor="@color/colorPrimary"
        android:textSize="@dimen/text_size_16" />
</LinearLayout>

這裏用的是TextView而沒有用Button,是因爲個人覺得點擊Button的
時候出現的陰影出超出下方邊緣,這樣會影響視覺效果。

整個佈局在底部,通過android:gravity=”bottom”來控制。

一共有5個按鈕,共分爲4種:
最頂上的一個TextView爲上方2個圓角
中間2個位爲矩形不帶圓角
倒數第二個爲下方2個圓角
最後一個爲全到圓角

怎樣畫圓角?
下面給出其中一個TextView的樣式top_round_normal.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:angle="90"
        android:endColor="@color/little_grey"
        android:startColor="@color/little_grey" />

    <!--設置圓角 上方圓角未點擊-->
    <corners
        android:bottomLeftRadius="0dp"
        android:bottomRightRadius="0dp"
        android:topLeftRadius="5dp"
        android:topRightRadius="5dp" />
</shape>

在shape根標籤中表明瞭是畫rectangle矩形。gradient是指漸變色,這
裏用的是同一種顏色。而corners標籤下的四個屬性顧名思義就是指定矩
形四個角的弧度的。

繪製完圓角後,發現TextView是有點擊反饋效果的。自然而然想到了寫
一個selector來區分點擊的狀態和正常狀態,top_round_normal.xml是
正常狀態,點擊狀態只需要更換一下gradient標籤中的顏色即可。

給出其中一個selector代碼:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/top_round_normal" android:state_focused="false" android:state_pressed="false" />
    <item android:drawable="@drawable/top_round_pressed" android:state_focused="true" android:state_pressed="true" />
    <item android:drawable="@drawable/top_round_pressed" android:state_focused="false" android:state_pressed="true" />
</selector>

然後通過background設置給TextView即可。

自定義Dialog視圖完成,下面該說說怎麼實現彈出Dialog了。

Dialog dialog = new Dialog(this, R.style.transparentFrameWindowStyle);

得到一個Dialog的實例,第二個參數爲Dialog的樣式。

    <style name="transparentFrameWindowStyle" parent="android:style/Theme.Dialog">
        <item name="android:windowBackground">@drawable/photo_choose_bg</item>
    </style>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/trans" />

    <!--四個圓角 未點擊-->
    <corners android:radius="20dp" />
    <padding
        android:bottom="5dp"
        android:left="5dp"
        android:right="5dp"
        android:top="5dp" />
</shape>

這裏設置顏色爲#00000000透明色,是爲了將Dialog的背景色與
整個窗體顏色保持一致以達到是一個整體的效果。

    Dialog dialog = new Dialog(this, 
    R.style.transparentFrameWindowStyle);
    dialog.setContentView(view, 
        new ViewGroup.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT, 
        ViewGroup.LayoutParams.WRAP_CONTENT));

然後將view設置給dialog顯示出來並設置寬高。

在Dialog彈出是伴隨着進來和出去兩種動畫效果。
在res目錄下新建anim文件夾,新建2個資源文件。

dialog_anim_in.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="500"
        android:fromXDelta="0"
        android:fromYDelta="1000"
        android:toXDelta="0"
        android:toYDelta="0" />
</set>

dialog_anim_out:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="500"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="0"
        android:toYDelta="1000" />
</set>
        Window window = dialog.getWindow();
        window.setWindowAnimations(R.style.anim_style);
        WindowManager.LayoutParams layoutParams = 
                    window.getAttributes();
        layoutParams.x = 0;
        layoutParams.y = 
        getWindowManager().getDefaultDisplay().getHeight();
        //保證dialog窗體可以水平鋪滿
        layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT; 
        layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
        //設置dialog的擺放位置
        dialog.onWindowAttributesChanged(layoutParams);
        //設置點擊dialog以爲的區域dialog消失
        dialog.setCanceledOnTouchOutside(true);
        dialog.show();

獲取到Dialog所在的窗體,然後通過window.setWindowAnimations()
方法設置動畫。方法接收一個style。

style中正好有

android:windowEnterAnimation //進入動畫
android:windowExitAnimation //退出動畫

因此在style文件中定義好動畫,然後設置給setWindowAnimations().

<style name="anim_style">
        <item name="android:windowEnterAnimation">@anim/dialog_anim_in</item>
        <item name="android:windowExitAnimation">@anim/dialog_anim_out</item>
    </style>

最後設置寬高和擺放位置show出來。

最後需要提一點的是,由於這些按鈕都是TextView,直接點擊是
沒有變色效果的,這是因爲還沒有給它們增加監聽。
我們可以給它們設置一個空監聽也可。

 dialog.findViewById(R.id.tv_take_dy_photo).setOnClickListener(null);

由於個人水平有限,整個過程描述的比較零散,特此獻上小Demo
完整Demo在這裏

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章