首先這個話題內容並不多,因爲我們沒有服務器,所以只能用線程來模擬登陸,從編寫界面到實現功能都要模仿的像一點對吧。
內容實現從登錄過程,到最後強制下線這一整套過程
下面來分步實現
一. 登陸界面
先上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代替(默認狀態下隱藏)
最後的效果呢??
在這裏!
額,是不是有點太像了,會不會被告侵權呢,哈哈!
其實點睛的設計在配色和動畫上面,配色一塊我覺得用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