QQ show——登錄及強制下線

首先這個話題內容並不多,因爲我們沒有服務器,所以只能用線程來模擬登陸,從編寫界面到實現功能都要模仿的像一點對吧。

內容實現從登錄過程,到最後強制下線這一整套過程
下面來分步實現

一. 登陸界面

先上Android QQ 6.5登錄界面效果
效果
下面我們從佈局xml開始寫起

在做之前說一下,由於這裏用的頭像是ps的圓形頭像,所以沒使用圓形頭像庫,下面直接用。
新建qq_login.xml佈局,內容如下

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#eeebecec"
    >
    <ImageView
        android:layout_width="90dp"
        android:layout_height="90dp"
        android:id="@+id/imageView2"
        android:background="@drawable/qq_head"
        android:layout_marginTop="43dp"
        android:layout_below="@+id/relativeLayout"
        android:layout_centerHorizontal="true" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:text="無法登陸?"
        android:id="@+id/textView7"
        android:textColor="#3eb0f2"
        android:layout_marginStart="14dp"
        android:layout_marginBottom="10dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:text="新用戶註冊"
        android:textColor="#3eb0f2"
        android:id="@+id/textView8"
        android:layout_alignTop="@+id/textView7"
        android:layout_alignParentEnd="true"
        android:layout_marginEnd="14dp" />
   <EditText
        android:layout_width="wrap_content"
        android:layout_height="42dp"
        android:inputType="number"
        android:ems="10"
        android:hint="QQ帳號/手機號/郵箱"
        android:textColorHint="#e4e3e3"
        android:background="@drawable/qq_edit_shape"
        android:id="@+id/editText"
        android:paddingStart="15dp"
        android:layout_below="@+id/imageView2"
        android:layout_alignParentStart="true"
        android:layout_marginTop="25dp"
        android:layout_alignParentEnd="true" />
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="42dp"
        android:inputType="textPassword"
        android:ems="10"
        android:id="@+id/editText2"
        android:hint="密碼"
        android:paddingStart="15dp"
        android:textColorHint="#e4e3e3"
        android:background="@drawable/qq_edit_shape"
        android:layout_below="@+id/editText"
        android:layout_alignParentStart="true"
        android:layout_alignParentEnd="true" />
    <ImageView
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:id="@+id/imageView4"
        android:layout_marginLeft="1dp"
        android:visibility="gone"
        android:background="@drawable/clear"
        android:layout_margin="50dp"
        android:layout_alignTop="@+id/editText"
        android:layout_alignStart="@+id/textView8" />
    <ImageView
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:id="@+id/imageView5"
        android:visibility="gone"
        android:background="@drawable/clear"
       android:layout_marginTop="10dp"
        android:layout_alignTop="@+id/editText"
        android:layout_alignEnd="@+id/imageView4"
        android:layout_marginEnd="1dp" />
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:id="@+id/imageView3"
        android:background="#dbd9d9"
        android:layout_above="@+id/editText2"
        android:layout_alignParentStart="true" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="42dp"
        android:text="登 錄"
        android:id="@+id/button"
        android:textColor="#fff"
        android:textSize="18sp"
        android:background="@drawable/login_btn_selector"
        android:layout_marginTop="18dp"
        android:layout_below="@+id/editText2"
        android:layout_alignEnd="@+id/textView8"
        android:layout_toEndOf="@+id/relativeLayout" />
</RelativeLayout>

從上到下分析,頭像是事先做好的圓形這裏代替一下,輸入框背景是一個shape形狀,所以在drawable下新建qq_edit_shape.xml,內容如下

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <solid android:color="#fafbfb"/>
</shape>

按鈕也是shape形狀,不過我們需要做兩個,並且還要添加一個背景選擇器

初始狀態shape

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <corners
        android:bottomLeftRadius="10px"
        android:bottomRightRadius="10px"
        android:topLeftRadius="10px"
        android:topRightRadius="10px" />
    <solid android:color="#09c2fa"/>
</shape>

按下時

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <corners
        android:bottomLeftRadius="10px"
        android:bottomRightRadius="10px"
        android:topLeftRadius="10px"
        android:topRightRadius="10px" />
    <solid android:color="#04c8eb"/>
</shape>

選擇器

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

然後是edittext分割線,用imageview代替,輸入時顯示的清除鍵,也用imageview代替(默認狀態下隱藏)

最後的效果呢??
在這裏!
demo

額,是不是有點太像了,會不會被告侵權呢,哈哈!
其實點睛的設計在配色和動畫上面,配色一塊我覺得用photoshop吸管可以檢測出來搭配,但是我的這個顏色是根據知乎某網友給的rgb搭配的,模擬器上是這個效果,真機上會有差別,動畫那一塊就不實現了。

二.實現模擬登陸過程

由於文章的重點是強制下線,所以登錄這個我們就用簡單的if-else來判斷一下就可以
首先我們來新建ActivityCollector類來管理所有類

public class ActivityCollector {
    public static List<Activity> activities=new ArrayList<Activity>();
    public static void addActivity(Activity activity)
    {
        activities.add(activity);
    }
    //添加
    public static void removeActivty(Activity activity)
    {
        activities.remove(activity);
    }
    //移除
    public static void finishAll()
    {
        for(Activity activty:activities)
        {
            if(!activty.isFinishing())
            {
                activty.finish();
            }
        }
    }
    //結束
}

接着建立活動父類

public class BaseActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityCollector.addActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityCollector.removeActivty(this);
    }
}

最後我們新建Login_Activity.java(注意:爲了接收管理器管理我們要繼承自BaseActivity)
在活動裏聲明用到的變量,oncreate方法裏新建初始化的initView()方法
方法內容如下:

 private void initView() {
        login= (Button) findViewById(R.id.button);
        //取的按鈕實例
        QQ= (EditText) findViewById(R.id.editText);
        //取的qq號輸入框實例
        pw= (EditText) findViewById(R.id.editText2);
        //密碼輸入框實例
        clearpw= (ImageView) findViewById(R.id.imageView4);
        clearQQ= (ImageView) findViewById(R.id.imageView5);
        //清除圖標實例
    }

把需要用到的控件初始化
下面設置監聽,在initView()方法後面新建initlistener();方法,內容如下

  private void initlistener() {
        //獲取輸入情況
        QQ.addTextChangedListener(textWatcher);
        pw.addTextChangedListener(textWatcher2);
        clearQQ.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                QQ.setText("");
            }
        });
        clearpw.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                pw.setText("");
            }
        });
        //清除數據
        login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Q = QQ.getText().toString();
                P = pw.getText().toString();
                //獲取輸入的文本
                if (Q.equals("") || P.equals("")) {
                    if (Q.equals("")) {
                        Toast toast = Toast.makeText(getApplicationContext(),
                                "請輸入帳號!", Toast.LENGTH_LONG);
                        toast.setGravity(Gravity.TOP, 0, 20);
                        toast.show();
                    }
                   else  if (P.equals("")) {
                        Toast toast = Toast.makeText(getApplicationContext(),
                                "請輸入密碼!", Toast.LENGTH_LONG);
                        toast.setGravity(Gravity.TOP, 0, 20);
                        toast.show();
                    }
                }
                //輸入時的判斷
                //開啓子線程模擬耗時操作
                else {
                    dialogshow();
                    new Thread() {
                        @Override
                        public void run() {
                            Message message = new Message();
                            try {
                                Thread.sleep(2000);
                                if (Q.equals("123456") && P.equals("123456")) {
                                    message.what = 1;
                                }
                                //如果帳號密碼匹配,發送信息
                                else {
                                    message.what = 0;
                                }
                                //不匹配發送消息
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            handler.sendMessage(message);
                        }
                    }.start();
                }
            }
        });

    }

這裏我們用textWatcher方法監聽是否輸入內容,從而控制清除圖標的顯示與隱藏
其中用到的textWatcher 和textWatcher2方法如下

 private TextWatcher textWatcher = new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before,
                                  int count) {
            if(s.length()>0) {
                clearQQ.setVisibility(View.VISIBLE);
            }
            else
            {
                clearQQ.setVisibility(View.GONE);
            }
        }
        //如果有輸入值就顯示圖標,沒有就隱藏
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                                      int after) {
        }
        @Override
        public void afterTextChanged(Editable s) {
        }
    };
    private TextWatcher textWatcher2 = new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before,
                                  int count) {
            if(s.length()>0) {
                clearpw.setVisibility(View.VISIBLE);
            }
            else
            {
                clearpw.setVisibility(View.GONE);
            }
        }
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                                      int after) {
        }
        @Override
        public void afterTextChanged(Editable s) {
        }
    };

這裏我們使用自定義dialog,xml就不貼了
dialogshow方法

 Dialog dia;
    private void dialogshow() {
        LayoutInflater layoutInflater=LayoutInflater.from(this);    //設置反射器
        View my=layoutInflater.inflate(R.layout.qq_login_dialog,null);
        //創建反射器視圖my,(採用了反射器的inflate方法)
        AlertDialog.Builder builder=new AlertDialog.Builder(this);
        //創建對話框實例
        builder.setView(my);
        //設置好視圖
        dia=builder.create();    //顯示出來
        Window dialogWindow = dia.getWindow();
        WindowManager.LayoutParams lp = dialogWindow.getAttributes();
        dialogWindow.setGravity( Gravity.TOP);
        //設置顯示位置
        dia.show();
        dia.setCanceledOnTouchOutside(false);   //點擊屏幕不消失
    }

線程結束信息接收
Handler方法

 private Handler handler=new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what)
            {
                case 1:
                    dia.dismiss();
                    Intent intent=new Intent(Login_Activty.this,QQActivity.class);
                    startActivity(intent);
                    finish();
                    //啓動新活動,結束本活動
                    break;
                case 0:
                    dia.dismiss();
                    Toast toast = Toast.makeText(getApplicationContext(),
                            "帳號或密碼輸入錯誤", Toast.LENGTH_LONG);
                    toast.setGravity(Gravity.TOP, 0, 20);
                    toast.show();

                    break;
                default:break;
            }
        }
    };

好了,Login_Activity裏的所有添加的方法就寫完了
最後梳理一下,貼出onCreate方法

  protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.qq_login);
        initView();
        initlistener();

    }

現在可以從oncreate進去一步一步的找到相應的方法,dialog佈局就不貼出來了,很簡單的一個progressbar和textview

三.廣播發出與接收

通過登錄界面進入新界面後,需要執行的是發送與接收廣播,於是廣播發送寫在了新活動裏

public class QQActivity extends BaseActivity  {
    Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       setContentView(R.layout.qqactivity);
        button= (Button) findViewById(R.id.buttonx);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent=new Intent("com.surine.android_su.OFFLINE");
                sendBroadcast(intent);
                //發送廣播
            }
        });
    }
}

佈局就不貼了,就一個按鈕而已
有了發送器我們需要接收器

public class OffReceiver extends BroadcastReceiver {
    Button button;
    @Override
    public void onReceive(final Context context, Intent intent) {
        LayoutInflater layoutInflater=LayoutInflater.from(context);    //設置反射器
        View my=layoutInflater.inflate(R.layout.offdialog,null);
        //創建反射器視圖my,(採用了反射器的inflate方法)
        AlertDialog.Builder builder=new AlertDialog.Builder(context);
        //創建對話框實例
        builder.setView(my);
        //設置好視圖

        builder.setCancelable(false);
        //不可取消
        final AlertDialog alertDialog=builder.create();

        alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        alertDialog.show();
        my.findViewById(R.id.dialog_confirm2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                alertDialog.dismiss();
                //消失
                ActivityCollector.finishAll();
                Intent intent=new Intent(context,Login_Activty.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(intent);
            //啓動新活動
            }
        });
    }
}

這裏先說用到的佈局dialog

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="320dp"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:orientation="vertical"
    android:background="@drawable/qqshape"
    tools:context=".MainActivity">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="50dip"
        android:layout_gravity="center"
        android:gravity="center"
        android:focusable="false"
        android:text="下線通知"
        android:textColor="#0e0e0e"
        android:textSize="18sp"
        android:textStyle="bold"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="60sp"
        android:paddingLeft="10dip"
        android:focusable="false"
        android:paddingRight="10dip"
        android:gravity="center_vertical"
        android:text="您已通過QQ安全中心退出手機QQ"
        android:textColor="#0e0e0e"
        android:textSize="16sp"
        />
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#c3c1c1"

        />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_alignParentBottom="true">
        <Button
            android:id="@+id/dialog_confirm2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="確定"
            android:textColor="#2a78ed"
       android:background="@drawable/off_dialog_selector"
            />
    </LinearLayout>
</LinearLayout>

所需要的drawable資源
qqshape

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <corners
        android:bottomLeftRadius="20px"
        android:bottomRightRadius="20px"
        android:topLeftRadius="20px"
        android:topRightRadius="20px" />
    <solid android:color="#e8e9e9"/>
</shape>

按鈕背景選擇器
off_dialog_selector

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

按下顏色
off_dialog_button_press

<?xml version="1.0" encoding="UTF-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#bbbaba"/>
    <corners android:bottomLeftRadius="20px"
        android:bottomRightRadius="20px"/>

</shape>

初始顏色
off_dialog_button_shape

<?xml version="1.0" encoding="UTF-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#e8e9e9"/>
    <corners android:bottomLeftRadius="20px"
        android:bottomRightRadius="20px"
        />

</shape>

佈局就這麼多,當我們接收到廣播後,顯示出dialog,監聽按鈕事件,關閉dialog並啓動新活動,注意設置dialog不可取消以屏蔽其它動作

四.註冊權限與總結

懸浮窗

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

接收器註冊

   <receiver android:name=".OffReceiver">
            <intent-filter>
                <action android:name="com.surine.android_su.OFFLINE"/>
            </intent-filter>
        </receiver>

全部的內容就是這麼多啦
最後看看效果圖吧
這裏寫圖片描述

寫在最後:

1.注意懸浮窗權限是需要我們手動給的,去手機的安全中心給予應用權限才能顯示
2.註冊的接收器要寫在application標籤內部……爲什麼要說這個呢,因爲不是很理解呢,所以把他寫在了標籤外……接下來就是”激動人心“的找錯時間……
3.半個小時前我在這篇博客的結束地方加入了郭神的博客,我很驚奇markdown編輯器自動識別了連接,試着點擊了一下……回退回來的時候……文章的3/4都沒了……從上午保存那塊地方再敲下來,如果有什麼錯誤還請評論區指出,還要提醒一下寶寶們……記得保存再離開。
4.寫這些文章的原因是,我要爲我的Android入門做筆記,由於剛學Android,很多東西都不知道,碰見了不一定能記住,所以藉助網絡來幫我記住它們,如果有看的我的博客,希望對大家有所幫助。
5.最後還是加入郭神的博客地址 http://guolin.tech,作爲Android入門的指導大神,他的《第一行代碼》還是很值得閱讀的。本篇內容實現是參考本書來的。
6.廣播接收器也算告一段落啦,當然我研究的比較淺顯,哈哈,大家結合上一篇內容讀吧!http://blog.csdn.net/su_ling/article/details/52205846

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