QQ show——登录及强制下线
来源:互联网 发布:python 数组加一列 编辑:程序博客网 时间:2024/05/16 10:10
首先这个话题内容并不多,因为我们没有服务器,所以只能用线程来模拟登陆,从编写界面到实现功能都要模仿的像一点对吧。
内容实现从登录过程,到最后强制下线这一整套过程
下面来分步实现
一. 登陆界面
先上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
- QQ show——登录及强制下线
- 登录界面+广播强制下线
- 广播的巧妙利用——仿QQ实现强制下线功能
- Android—强制下线功能的实现
- Broadcast学习--模仿qq强制下线功能
- 实现单点登录并强制对方下线
- 广播的最佳实践——实现强制下线功能
- android学习笔记——BroadcastReceiver实现强制下线
- 广播的最佳实践——实现强制下线功能
- 广播实践部分——实现强制下线功能
- 广播的最佳实践——实现强制下线功能
- 广播的最佳实践——实现强制下线功能
- 广播的最佳实践——实现强制下线功能
- 单机登录实现思路(强制下线其他用户)
- 用户登录之后实现强制下线的功能
- Android笔记(二十六)广播实践——实现强制下线功能
- Linux强制用户下线
- android强制下线
- 批渲染的一个坑
- HTTP协议
- 【转】How To Ask Questions The Smart Way---提问的智慧
- Android小程序--跟随手机移动的小球
- 最小生成树-Prim算法和Kruskal算法
- QQ show——登录及强制下线
- HDU 5743 Join The Future 给定部分区间和奇偶,和数字范围,求方案数 DP
- Bootstrapping Face Detection with Hard Negative Examples,arxiv 16.08
- tcp三次握手四次挥手
- android可执行文件出现error: only position independent executables (PIE) are supported.
- JS中style、currentStyle、getComputedStyle的区别
- <mvc:annotation-driven/>的作用
- 开发小技巧:1.iOS初始化系统主题
- Anti-Debugging Skills In APK