您的位置:首页 > 产品设计 > UI/UE

环信UI开源Demo情景分析四、登陆界面

2015-04-24 08:36 357 查看
接下来咱们来分析下登录界面,根据清单文件的配置不难发现接下来的Activity基本都是竖屏显示,以及与启动界面一样的动画:

<!-- 登陆 -->
<activity
android:name=".activity.LoginActivity"
android:screenOrientation="portrait"
android:theme="@style/horizontal_slide" >
</activity>


在下面的代码中有一处很神奇的逻辑,如果光从这个登录逻辑来看,不讨论以后的需要的话应该是不可能执行的:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 如果用户名密码都有,直接进入主页面
if (DemoHXSDKHelper.getInstance().isLogined()) {
autoLogin = true;
startActivity(new Intent(LoginActivity.this, MainActivity.class));
return;
}
setContentView(R.layout.activity_login);
usernameEditText = (EditText) findViewById(R.id.username);
passwordEditText = (EditText) findViewById(R.id.password);
// 如果用户名改变,清空密码
usernameEditText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
passwordEditText.setText(null);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
if (DemoApplication.getInstance().getUserName() != null) {
usernameEditText.setText(DemoApplication.getInstance().getUserName());
}
}


没错,就是第五行,是不是有点熟悉,对,他就是在启动界面的逻辑,正因为没有登录才跳转到这个界面,结果在这个界面又判断一次,好吧,可能是以后有大用,先不管这个,咱们继续往下看,接下来是一个对用户名改变的监听,改变之后让密码清空。

最后面是对用户名的判断,咱们点进去看看到底是怎么存储用户名的:

/**
* 获取当前登陆用户名
* @return
*/
public String getUserName() {
return hxSDKHelper.getHXId();
}
/**
* 设置用户名
* @param user
*/
public void setUserName(String username) {
hxSDKHelper.setHXId(username);
}


这个是在APP类中的set,get方法通过Helper实例来保存的,至于到底保存在哪里了,后面碰到了再说。

/**
* 登录
*
* @param view
*/
public void login(View view) {
if (!CommonUtils.isNetWorkConnected(this)) {
Toast.makeText(this, R.string.network_isnot_available, Toast.LENGTH_SHORT).show();
return;
}
currentUsername = usernameEditText.getText().toString().trim();
currentPassword = passwordEditText.getText().toString().trim();

if(TextUtils.isEmpty(currentUsername)){
Toast.makeText(this, R.string.User_name_cannot_be_empty, Toast.LENGTH_SHORT).show();
return;
}
if(TextUtils.isEmpty(currentPassword)){
Toast.makeText(this, R.string.Password_cannot_be_empty, Toast.LENGTH_SHORT).show();
return;
}
Intent intent = new Intent(LoginActivity.this, com.easemob.chatuidemo.activity.AlertDialog.class);
intent.putExtra("editTextShow", true);
intent.putExtra("titleIsCancel", true);
intent.putExtra("msg", getResources().getString(R.string.please_set_the_current));
intent.putExtra("edit_text", currentUsername);
startActivityForResult(intent, REQUEST_CODE_SETNICK);
}


在填完账号密码后就是可以登录了,首先是对网络状态的判断,

/**
* 检测网络是否可用
* @param context
* @return
*/
public static boolean isNetWorkConnected(Context context) {
if (context != null) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if (mNetworkInfo != null) {
return mNetworkInfo.isAvailable();
}
}
return false;
}


没有网的情况下会直接提示返回。假设当前咱们条件俱全,下面是对输入的判断,接下来启动一个有返回的AlertDialog并附带一些内容。



很显然,这是一个自定义的对话框,功能是设置昵称。

<!-- 自定义的alertdialog -->
<activity
android:name=".activity.AlertDialog"
android:screenOrientation="portrait"
android:theme="@style/MyDialogStyle" >
</activity>


<style name="MyDialogStyle">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<item name="android:backgroundDimEnabled">true</item>
</style>


设置了一下风格:

windowBackground:设置dialog的背景 默认的 windowBackground 定义为screen_background_dark,可以在frameworks\base\core\res\res\values\colors.xml
中找到,定义为:<drawable name="screen_background_dark">#ff000000</drawable> 现在设置为transparent 顺便说一下,如果自定义Theme中将android:windowBackground置为null,能小幅提升界面的绘制效率。

windowFrame:Dialog的windowFrame框为无

windowNoTitle:是否显示title

windowIsFloating:是否浮现在activity之上

windowIsTranslucent:是否半透明

windowContentOverlay:窗口内容的前景之上的可绘制资源。默认情况下,就是状态栏下的阴影

windowAnimationStyle:窗口动画风格 使用的是默认的

backgroundDimEnabled:背景是否模糊显示
显示

这个自定义的对画框说完了,接下来继续看这个对话框是怎能运作的。

mTextView = (TextView) findViewById(R.id.title);
mButton = (Button) findViewById(R.id.btn_cancel);
imageView = (ImageView) findViewById(R.id.image);
editText = (EditText) findViewById(R.id.edit);


其中有四个控件,分别显示标题、按钮、图案和一个编辑框。跟上面截图一样。

传过去的参数有:

intent.putExtra("editTextShow", true);
intent.putExtra("titleIsCancel", true);
intent.putExtra("msg", getResources().getString(R.string.please_set_the_current));
intent.putExtra("edit_text", currentUsername);


这边获取到响应的内容:

//提示内容
String msg = getIntent().getStringExtra("msg");
//提示标题
String title = getIntent().getStringExtra("title");
position = getIntent().getIntExtra("position", -1);
//是否显示取消标题
boolean isCanceTitle=getIntent().getBooleanExtra("titleIsCancel", false);
//是否显示取消按钮
boolean isCanceShow = getIntent().getBooleanExtra("cancel", false);
//是否显示文本编辑框
isEditextShow = getIntent().getBooleanExtra("editTextShow",false);
//转发复制的图片的path
String path = getIntent().getStringExtra("forwardImage");
//
String edit_text = getIntent().getStringExtra("edit_text");
if(msg != null)
            ((TextView)findViewById(R.id.alert_message)).setText(msg);
        if(title != null)
            mTextView.setText(title);
        if(isCanceTitle){
            mTextView.setVisibility(View.GONE);
        }
        if(isCanceShow)
            mButton.setVisibility(View.VISIBLE);
        if(path != null){
             //优先拿大图,没有去取缩略图
            if(!new File(path).exists())
                path = DownloadImageTask.getThumbnailImagePath(path);
            imageView.setVisibility(View.VISIBLE);
            ((TextView)findViewById(R.id.alert_message)).setVisibility(View.GONE);
            if(ImageCache.getInstance().get(path) != null){
                imageView.setImageBitmap(ImageCache.getInstance().get(path));
            }else{
                Bitmap bm = ImageUtils.decodeScaleImage(path, 150, 150);
                imageView.setImageBitmap(bm);
                ImageCache.getInstance().put(path, bm);
            }
            
        }
        if(isEditextShow){
            editText.setVisibility(View.VISIBLE);
            editText.setText(edit_text);
        }
然后根据所需要的,显示出来。就是我们所看到的。

public void ok(View view){
setResult(RESULT_OK,new Intent().putExtra("position", position).
putExtra("edittext", editText.getText().toString())
/*.putExtra("voicePath", voicePath)*/);
if(position != -1)
ChatActivity.resendPos = position;
finish();
}
public void cancel(View view){
finish();
}
@Override
public boolean onTouchEvent(MotionEvent event){
finish();
return true;
}
其中还有两个按钮,以及非模态。并且设置返回内容为编辑框中的内容。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_CODE_SETNICK) {
DemoApplication.currentUserNick = data.getStringExtra("edittext");
progressShow = true;
final ProgressDialog pd = new ProgressDialog(LoginActivity.this);
pd.setCanceledOnTouchOutside(false);
pd.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
progressShow = false;
}
});
pd.setMessage(getString(R.string.Is_landing));
pd.show();
final long start = System.currentTimeMillis();
// 调用sdk登陆方法登陆聊天服务器
EMChatManager.getInstance().login(currentUsername, currentPassword, new EMCallBack() {
@Override
public void onSuccess() {
if (!progressShow) {
return;
}
// 登陆成功,保存用户名密码
DemoApplication.getInstance().setUserName(currentUsername);
DemoApplication.getInstance().setPassword(currentPassword);

runOnUiThread(new Runnable() {
public void run() {
pd.setMessage(getString(R.string.list_is_for));
}
});
try {
// ** 第一次登录或者之前logout后再登录,加载所有本地群和回话
// ** manually load all local groups and
// conversations in case we are auto login
EMGroupManager.getInstance().loadAllGroups();
EMChatManager.getInstance().loadAllConversations();
// 处理好友和群组
processContactsAndGroups();
} catch (Exception e) {
e.printStackTrace();
// 取好友或者群聊失败,不让进入主页面
runOnUiThread(new Runnable() {
public void run() {
pd.dismiss();
DemoApplication.getInstance().logout(null);
Toast.makeText(getApplicationContext(), R.string.login_failure_failed, 1).show();
}
});
return;
}
// 更新当前用户的nickname 此方法的作用是在ios离线推送时能够显示用户nick
boolean updatenick = EMChatManager.getInstance().updateCurrentUserNick(DemoApplication.currentUserNick.trim());
if (!updatenick) {
Log.e("LoginActivity", "update current user nick fail");
}
if (!LoginActivity.this.isFinishing())
pd.dismiss();
// 进入主页面
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
}

@Override
public void onProgress(int progress, String status) {
}

@Override
public void onError(final int code, final String message) {
if (!progressShow) {
return;
}
runOnUiThread(new Runnable() {
public void run() {
pd.dismiss();
Toast.makeText(getApplicationContext(), getString(R.string.Login_failed) + message, Toast.LENGTH_SHORT).show();
}
});
}
});

}
}
}
这里面就是登录的内容了,

先设置APP里的昵称,

/**
* 当前用户nickname,为了苹果推送不是userid而是昵称
*/
public static String currentUserNick = "";
然后设置一个圆形进度条,点击外部不退出,点击进度条取消。后面是调用SDK进行登录,并且保存用户名和密码,获取相关本地组和联系人信息。如果获取信息异常,则退出登录。成功后更新昵称。并且取消进度条,进入主界面。

private void processContactsAndGroups() throws EaseMobException {
// demo中简单的处理成每次登陆都去获取好友username,开发者自己根据情况而定
List<String> usernames = EMContactManager.getInstance().getContactUserNames();
EMLog.d("roster", "contacts size: " + usernames.size());
Map<String, User> userlist = new HashMap<String, User>();
for (String username : usernames) {
User user = new User();
user.setUsername(username);
setUserHearder(username, user);
userlist.put(username, user);
}
// 添加user"申请与通知"
User newFriends = new User();
newFriends.setUsername(Constant.NEW_FRIENDS_USERNAME);
String strChat = getResources().getString(R.string.Application_and_notify);
newFriends.setNick(strChat);

userlist.put(Constant.NEW_FRIENDS_USERNAME, newFriends);
// 添加"群聊"
User groupUser = new User();
String strGroup = getResources().getString(R.string.group_chat);
groupUser.setUsername(Constant.GROUP_USERNAME);
groupUser.setNick(strGroup);
groupUser.setHeader("");
userlist.put(Constant.GROUP_USERNAME, groupUser);

// 存入内存
DemoApplication.getInstance().setContactList(userlist);
System.out.println("----------------" + userlist.values().toString());
// 存入db
UserDao dao = new UserDao(LoginActivity.this);
List<User> users = new ArrayList<User>(userlist.values());
dao.saveContactList(users);

// 获取黑名单列表
List<String> blackList = EMContactManager.getInstance().getBlackListUsernamesFromServer();
// 保存黑名单
EMContactManager.getInstance().saveBlackList(blackList);

// 获取群聊列表(群聊里只有groupid和groupname等简单信息,不包含members),sdk会把群组存入到内存和db中
EMGroupManager.getInstance().getGroupsFromServer();
}
后面是获取联系人信息,并且对每个联系人这是header,方便查找。并保存到本地数据库当中。

/**
* 设置hearder属性,方便通讯中对联系人按header分类显示,以及通过右侧ABCD...字母栏快速定位联系人
* @param username
* @param user
*/
protected void setUserHearder(String username, User user) {
String headerName = null;
if (!TextUtils.isEmpty(user.getNick())) {
headerName = user.getNick();
} else {
headerName = user.getUsername();
}
if (username.equals(Constant.NEW_FRIENDS_USERNAME)) {
user.setHeader("");
} else if (Character.isDigit(headerName.charAt(0))) {
user.setHeader("#");
} else {
user.setHeader(HanziToPinyin.getInstance().get(headerName.substring(0, 1)).get(0).target.substring(0, 1).toUpperCase());
char header = user.getHeader().toLowerCase().charAt(0);
if (header < 'a' || header > 'z') {
user.setHeader("#");
}
}
}
没有昵称用账号名,并且设置字幕前缀。
/**
* 注册
* @param view
*/
public void register(View view) {
startActivityForResult(new Intent(this, RegisterActivity.class), 0);
}
@Override
protected void onResume() {
super.onResume();
if (autoLogin) {
return;
}
}
对于11行,我很无解,不过不要在意这些细节。

登录界面就到这里了。按照正常流程,先注册一个账号,再继续往下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: