天花板谈Android开发膜拜单车-Mobike APPAndroid技术知识

(非常火爆)高仿膜拜单车安卓APP--Mobike之手机登陆界面

2017-05-22  本文已影响339人  文采逸逸

版权声明:本文为Yiwent原创文章,转载必须注明出处。

1.登陆界面

对于一个网络APP来说,刚开始首先必须登录,膜拜使用有手机登陆,当然还有微信什么其他的,不过绑定微信后又要绑定手机,所以手机登陆是必须的。

先看效果图:

2.界面还比较简单,两个et 和两个bt.

xml文件:


xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="match_parent"

>

android:id="@+id/toolbar_login"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="?attr/colorPrimary"

android:minHeight="?attr/actionBarSize"

app:leftButtonIcon="@drawable/places_ic_clear"

app:showSearchView="false"

app:title="手机验证"

>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_below="@id/toolbar_login"

android:layout_margin="20dp"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="#F2F2F2"

android:orientation="horizontal">

android:layout_marginLeft="3dp"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="手机号"

android:textColor="#333333"

android:textSize="18dp"/>

android:id="@+id/et_phone"

android:layout_marginRight="3dp"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:hint="请输入手机号"

android:inputType="phone"

android:textColorHint="#ABABAB"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginTop="15dp"

android:background="#F2F2F2"

android:orientation="horizontal">

android:layout_width="0dp"

android:layout_marginLeft="3dp"

android:layout_height="wrap_content"

android:layout_weight="2"

android:text="验证码"

android:textColor="#333333"

android:textSize="18dp"/>

android:id="@+id/et_code"

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_weight="4"

android:hint="请输入验证码"

android:inputType="phone"

android:textColorHint="#ABABAB"/>

android:id="@+id/get_code"

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_weight="4"

android:background="@color/gray"

android:text="获取验证码"

android:textColor="@color/white"/>

android:id="@+id/loin_voice"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="2dp"

android:layout_marginTop="8dp"

android:clickable="true"

android:text="收不到短信,试试语音短信"

android:textColor="@color/red"/>

android:id="@+id/login_query"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginTop="8dp"

android:layout_marginEnd="8dp"

android:background="@color/gray"

android:text="确定"

android:textColor="@color/white"/>

android:layout_marginTop="15dp"

android:gravity="center"

android:layout_width="match_parent"

android:orientation="horizontal"

android:layout_height="wrap_content">

android:text="点击-确定,即表示已阅读并同意"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

android:id="@+id/login_services"

android:text="《用车服务条款》"

android:textColor="@color/red"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

其中

3.MyToolBar和ClearEditText 为自定义控件。

myToolBar代码:

package com.yiwen.mobike.views;

import android.content.Context;

import android.graphics.drawable.Drawable;

import android.support.annotation.StringRes;

import android.support.v7.app.ActionBar;

import android.support.v7.widget.TintTypedArray;

import android.support.v7.widget.Toolbar;

import android.util.AttributeSet;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.EditText;

import android.widget.ImageView;

import android.widget.TextView;

import com.yiwen.mobike.R;

/**

* User: Yiwen(https://github.com/yiwent)

* Date: 2017-05-02

* Time: 11:00

* FIXME

*/

public class MyToolBar extends Toolbar {

private LayoutInflater mInflater;

private View          mView;

private TextView      toolbar_title;

private EditText      toolbar_searchview;

private ImageView      toolbar_leftButton;

private ImageView      toolbar_rightButton;

private boolean        showSearchView;

private Drawable      left_button_icon;

private Drawable      right_button_icon;

private String        title;

public MyToolBar(Context context) {

this(context, null);

}

public MyToolBar(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public MyToolBar(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

initview();

if (attrs != null) {

final TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,

R.styleable.MyToolBar, defStyleAttr, 0);

showSearchView = a.getBoolean(R.styleable.MyToolBar_showSearchView, false);

left_button_icon = a.getDrawable(R.styleable.MyToolBar_leftButtonIcon);

right_button_icon = a.getDrawable(R.styleable.MyToolBar_rightButtonIcon);

title = a.getString(R.styleable.MyToolBar_myTitle);

a.recycle();

}

isShouw();

setContentInsetsRelative(15, 15);

initListener();

}

private void initListener() {

toolbar_leftButton.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

if (onLeftButtonClickListener != null) {

onLeftButtonClickListener.onClick();

}

}

});

toolbar_rightButton.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

if (onRightButtonClickListener != null) {

onRightButtonClickListener.onClick();

}

public void isShouw() {

if (showSearchView) {

showSearchview();

hideTitle();

} else {

hideSearchview();

showTitle();

if (title != null) {

toolbar_title.setText(title);

}

Log.d("left_button_icon", "initview:5"+left_button_icon);

if (left_button_icon != null) {

toolbar_leftButton.setVisibility(VISIBLE);

toolbar_leftButton.setBackground(left_button_icon);

}

if (right_button_icon != null) {

toolbar_rightButton.setVisibility(VISIBLE);

toolbar_rightButton.setImageDrawable(right_button_icon);

}

public interface OnLeftButtonClickListener {

void onClick();

}

public interface OnRightButtonClickListener {

void onClick();

}

private OnLeftButtonClickListener  onLeftButtonClickListener;

private OnRightButtonClickListener onRightButtonClickListener;

public void setOnLeftButtonClickListener(OnLeftButtonClickListener listener) {

onLeftButtonClickListener = listener;

}

public void setOnRightButtonClickListener(OnRightButtonClickListener listener) {

onRightButtonClickListener = listener;

}

private void initview() {

if (mView == null) {

mInflater = LayoutInflater.from(getContext());

mView = mInflater.inflate(R.layout.toolbar, null);

toolbar_rightButton = (ImageView) mView.findViewById(R.id.id_btn_right);

toolbar_title = (TextView) mView.findViewById(R.id.id_tv_title);

toolbar_searchview = (EditText) mView.findViewById(R.id.id_et_search);

toolbar_leftButton = (ImageView) mView.findViewById(R.id.id_ib_navigation);

ActionBar.LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,

ViewGroup.LayoutParams.WRAP_CONTENT);

addView(mView, lp);

//            if (showSearchView) {

//                showSearchview();

//                hideTitle();

//            } else {

//                hideSearchview();

//                showTitle();

//                if (title != null) {

//                    toolbar_title.setText(title);

//                }

//            }

//            Log.d("left_button_icon", "initview:5"+left_button_icon);

//            if (left_button_icon != null) {

//

//                toolbar_leftButton.setBackground(left_button_icon);

//                toolbar_leftButton.setVisibility(VISIBLE);

//            }

//

//            if (right_button_icon != null) {

//                toolbar_rightButton.setImageDrawable(right_button_icon);

//                toolbar_rightButton.setVisibility(VISIBLE);

//            }

@Override

public void setTitle(@StringRes int resId) {

setTitle(getContext().getString(resId));

}

@Override

public void setTitle(CharSequence title) {

initview();

if (toolbar_title != null) {

toolbar_title.setText(title);

showTitle();

public void showSearchview() {

if (toolbar_searchview != null) {

toolbar_searchview.setVisibility(VISIBLE);

}

public void hideSearchview() {

if (toolbar_searchview != null) {

toolbar_searchview.setVisibility(GONE);

}

public void showTitle() {

if (toolbar_title != null) {

toolbar_title.setVisibility(VISIBLE);

}

public void hideTitle() {

if (toolbar_title != null) {

toolbar_title.setVisibility(GONE);

}

/**

* 设置左右按钮的图标

*

* @param d

*/

public void setLeftButtonIconDrawable(Drawable d) {

toolbar_leftButton.setImageDrawable(d);

toolbar_leftButton.setVisibility(VISIBLE);

}

public void setRightButtonIconDrawable(Drawable d) {

toolbar_rightButton.setImageDrawable(d);

toolbar_rightButton.setVisibility(VISIBLE);

}

/**

* 标题与搜索框的切换

*/

public void setShowSearchView() {

hideTitle();

showSearchview();

}

public void setShowTitleView(String title) {

hideSearchview();

showTitle();

toolbar_title.setText(title);

4.ClearEditText代码:

package com.yiwen.mobike.views;

import android.content.Context;

import android.graphics.drawable.Drawable;

import android.support.v4.content.ContextCompat;

import android.support.v4.graphics.drawable.DrawableCompat;

import android.support.v7.widget.AppCompatEditText;

import android.text.Editable;

import android.text.TextWatcher;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import com.yiwen.mobike.R;

public class ClearEditText extends AppCompatEditText implements View.OnTouchListener, View.OnFocusChangeListener, TextWatcher {

private Drawable mClearTextIcon;

private OnFocusChangeListener mOnFocusChangeListener;

private OnTouchListener mOnTouchListener;

public ClearEditText(final Context context) {

super(context);

init(context);

}

public ClearEditText(final Context context, final AttributeSet attrs) {

super(context, attrs);

init(context);

}

public ClearEditText(final Context context, final AttributeSet attrs, final int defStyleAttr) {

super(context, attrs, defStyleAttr);

init(context);

}

private void init(final Context context) {

final Drawable drawable = ContextCompat.getDrawable(context, R.mipmap.places_ic_clear);

final Drawable wrappedDrawable = DrawableCompat.wrap(drawable); //Wrap the drawable so that it can be tinted pre Lollipop

DrawableCompat.setTint(wrappedDrawable, getCurrentHintTextColor());

mClearTextIcon = wrappedDrawable;

//        mClearTextIcon= context.getResources().getDrawable(R.drawable.icon_delete_32);

mClearTextIcon.setBounds(0, 0, mClearTextIcon.getIntrinsicHeight(), mClearTextIcon.getIntrinsicHeight());

setClearIconVisible(false);

/*

* 设置父类的监听器,还可以单独给该类设置监听器

* */

super.setOnTouchListener(this);

super.setOnFocusChangeListener(this);

addTextChangedListener(this);

}

@Override

public void setOnFocusChangeListener(OnFocusChangeListener l) {

mOnFocusChangeListener = l;

}

@Override

public void setOnTouchListener(OnTouchListener l) {

mOnTouchListener = l;

}

@Override

public void onFocusChange(View v, boolean hasFocus) {

if (hasFocus) {

setClearIconVisible(getText().length() > 0);

} else {

setClearIconVisible(false);

}

if (mOnFocusChangeListener != null) {

mOnFocusChangeListener.onFocusChange(v, hasFocus);

}

}

@Override

public boolean onTouch(View view, MotionEvent motionEvent) {

final int x = (int) motionEvent.getX();

/*

判断是否触摸在清楚按钮上

* */

if (mClearTextIcon.isVisible() && x > getWidth() - getPaddingRight() - mClearTextIcon.getIntrinsicWidth()) {

if (motionEvent.getAction() == MotionEvent.ACTION_UP) {

setError(null);

setText("");

}

return true;

}

return mOnTouchListener != null && mOnTouchListener.onTouch(view, motionEvent);

}

@Override

public final void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {

if (isFocused()) {

setClearIconVisible(text.length() > 0);

}

}

@Override

public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@Override

public void afterTextChanged(Editable s) {

}

private void setClearIconVisible(final boolean visible) {

mClearTextIcon.setVisible(visible, false);

final Drawable[] compoundDrawables = getCompoundDrawables();

setCompoundDrawables(

compoundDrawables[0],

compoundDrawables[1],

visible ? mClearTextIcon : null,

compoundDrawables[3]);

}

}

非常简单的自定义控件,加了几个属性。

5.LoginActivity包含手机验证,和判断手机输入对错,控制控件颜色,膜拜主色为黑 、白、红还有灰色。

package com.yiwen.mobike.activity;

import android.content.Intent;

import android.os.Bundle;

import android.support.v7.app.AppCompatActivity;

import android.text.Editable;

import android.text.TextUtils;

import android.text.TextWatcher;

import android.util.Log;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

import com.yiwen.mobike.R;

import com.yiwen.mobike.utils.MyConstains;

import com.yiwen.mobike.utils.ToastUtils;

import com.yiwen.mobike.views.ClearEditText;

import com.yiwen.mobike.views.CountTimerView;

import com.yiwen.mobike.views.MyToolBar;

import org.json.JSONObject;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import butterknife.BindView;

import butterknife.ButterKnife;

import butterknife.OnClick;

import cn.smssdk.EventHandler;

import cn.smssdk.SMSSDK;

import cn.smssdk.utils.SMSLog;

public class LoginActivity extends AppCompatActivity {

private static final String TAG = "LoginActivity";

@BindView(R.id.toolbar_login)

MyToolBar    mToolbarLogin;

@BindView(R.id.et_phone)

ClearEditText mEtPhone;

@BindView(R.id.et_code)

EditText      mEtCode;

@BindView(R.id.get_code)

Button        mGetCode;

@BindView(R.id.loin_voice)

TextView      mLoinVoice;

@BindView(R.id.login_query)

Button        mLoginQuery;

@BindView(R.id.login_services)

TextView      mLoginServices;

private boolean isNeedLogin = true;

private TextView      mTvCountryCode;

private CountTimerView mCountTimeView;

private              int    phoneLength        = 0;

private              int    codeLength        = 0;

// 默认使用中国区号

private static final String DEFAULT_COUNTRY_ID = "42";

private SmsEventHandler mEventHandler;

private boolean isSendCode;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_login);

ButterKnife.bind(this);

intView();

initDate();

initEvent();

}

private void intView() {

ButterKnife.bind(this);

}

private void initDate() {

SMSSDK.initSDK(this, "1***3", "4***7");//mob注册获取密钥

mEventHandler = new SmsEventHandler();

SMSSDK.registerEventHandler(mEventHandler);

}

private void initEvent() {

mToolbarLogin.setOnLeftButtonClickListener(new MyToolBar.OnLeftButtonClickListener() {

@Override

public void onClick() {

Go2Main();

}

});

mEtPhone.addTextChangedListener(new TextWatcher() {

@Override

public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@Override

public void onTextChanged(CharSequence s, int start, int before, int count) {

phoneLength = s.length();

if (phoneLength > 0) {

setRed(mGetCode);

} else {

setGray(mGetCode);

}

if (phoneLength > 0 && codeLength > 0) {

setRed(mLoginQuery);

} else {

setGray(mLoginQuery);

}

}

@Override

public void afterTextChanged(Editable s) {

}

});

mEtCode.addTextChangedListener(new TextWatcher() {

@Override

public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@Override

public void onTextChanged(CharSequence s, int start, int before, int count) {

codeLength = s.length();

if (phoneLength > 0 && codeLength > 0) {

setRed(mLoginQuery);

} else {

setGray(mLoginQuery);

}

}

@Override

public void afterTextChanged(Editable s) {

}

});

}

/**

* 改变bt颜色red设置可点击

*

* @param bt

*/

private void setRed(Button bt) {

bt.setClickable(true);

bt.setBackgroundResource(R.color.red);

}

/**

* 改变bt颜色gray设置不可点击

*

* @param bt

*/

private void setGray(Button bt) {

bt.setClickable(false);

bt.setBackgroundResource(R.color.gray);

}

class SmsEventHandler extends EventHandler {

@Override

public void afterEvent(final int event, final int result, final Object data) {

runOnUiThread(new Runnable() {

@Override

public void run() {

//回调完成

if (result == SMSSDK.RESULT_COMPLETE) {

//返回支持发送验证码的国家列表

if (event == SMSSDK.EVENT_GET_SUPPORTED_COUNTRIES) {

//                            SMSSDK.getSupportedCountries();

onCountryListGot((ArrayList>) data);

//获取验证码成功

} else if (event == SMSSDK.EVENT_GET_VERIFICATION_CODE) {

// 请求验证码后,跳转到验证码填写页面

afterVerificationCodeRequested((Boolean) data);

//提交验证码成功

} else if (event == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE) {

// ToastUtils.show(LoginActivity.this, "验证码已发送");

mEtCode.setText("");

RegOK();

}

} else {

// 根据服务器返回的网络错误,给toast提示

try {

((Throwable) data).printStackTrace();

Throwable throwable = (Throwable) data;

JSONObject object = new JSONObject(

throwable.getMessage());

String des = object.optString("detail");

if (!TextUtils.isEmpty(des)) {

ToastUtils.show(LoginActivity.this, des);

return;

}

} catch (Exception e) {

SMSLog.getInstance().w(e);

}

}

}

});

}

private void RegOK() {

//        ToastUtils.show(LoginActivity.this, "注册成功");

getSharedPreferences(MyConstains.IS_NEED_LOGIN, MODE_PRIVATE)

.edit()

.putBoolean(MyConstains.IS_NEED_LOGIN, false)

.apply();

Go2Main();

}

}

/**

* 获得支持的国家列表

*

* @param data

*/

private void onCountryListGot(ArrayList> data) {

for (HashMap country : data) {

String code = (String) country.get("zone");

String rule = (String) country.get("rule");

if (TextUtils.isEmpty(code) || TextUtils.isEmpty(rule)) {

continue;

}

Log.d(TAG, "onCountryListGot: " + code + ":" + rule);

}

}

/**

* 请求验证码成功后跳转

*

* @param data

*/

private void afterVerificationCodeRequested(Boolean data) {

String phone = mEtPhone.getText().toString().trim().replace("\\s*", "");

//        String countryCode = mTvCountryCode.getText().toString().trim();

String countryCode = "86";

if (countryCode.startsWith("+")) {

countryCode = countryCode.substring(1);

}

isSendCode = false;

}

private void Go2Main() {

Intent intent = new Intent(LoginActivity.this, MainActivity.class);

startActivity(intent);

finish();

}

@OnClick({R.id.get_code, R.id.loin_voice, R.id.login_query, R.id.login_services})

public void onViewClicked(View view) {

switch (view.getId()) {

case R.id.get_code:

getCode();

break;

case R.id.loin_voice:

ToastUtils.show(LoginActivity.this,"语音验证");

break;

case R.id.login_query:

submitCode();

break;

case R.id.login_services:

ToastUtils.show(LoginActivity.this,"服务点击");

break;

}

}

/**

* 获取验证码

*/

private void getCode() {

String phone = mEtPhone.getText().toString().trim().replace("\\s*", "");

//      String countryCode = mTvCountryCode.getText().toString().trim();

String countryCode = "+86";

// String countryCode = mTvCountryCode.getText().toString().trim();

if (checkPhoneNum(phone, countryCode)) {

/*请求获得验证码*/

Log.d(TAG, "getCode: " + phone + "**" + countryCode);

SMSSDK.getVerificationCode(countryCode, phone);

mCountTimeView = new CountTimerView(mGetCode);

mCountTimeView.start();

}

}

/**

* 检查手机号格式

*

* @param phone

* @param countryCode

*/

private boolean checkPhoneNum(String phone, String countryCode) {

if (countryCode.startsWith("+")) {

countryCode = countryCode.substring(1);

}

if (TextUtils.isEmpty(phone)) {

mEtPhone.setError("手机号格式有误");

//ToastUtils.show(this, "请输入手机号码");

//            dissmissDialog();

return false;

}

if (countryCode.equals("86")) {

if (phone.length() != 11) {

mEtPhone.setError("手机号长度不正确");

// ToastUtils.show(this, "手机号长度不正确");

//                dissmissDialog();

return false;

}

}

String rule = "^1(3|5|7|8|4)\\d{9}";

Pattern compile = Pattern.compile(rule);

Matcher matcher = compile.matcher(phone);

if (!matcher.matches()) {

mEtPhone.setError("您输入的手机号码格式不正确");

// ToastUtils.show(this, "您输入的手机号码格式不正确");

// dissmissDialog();

return false;

}

return true;

}

private void submitCode() {

String code = mEtCode.getText().toString().trim();

String mPhone = mEtPhone.getText().toString().trim().replace("\\s*", "");

if (TextUtils.isEmpty(code)) {

mEtCode.setError("请输入验证码");

//            ToastUtils.show(this, "请输入验证码");

return;

}

Log.d(TAG, "submitCode: " + mPhone + code);

SMSSDK.submitVerificationCode("86", mPhone, code);

}

@Override

protected void onDestroy() {

super.onDestroy();

SMSSDK.unregisterEventHandler(mEventHandler);

}

}

6.最后说明:

验证手机号用了mob的SDK,经测试还是可以发短信的,不过用同一号码,两三次就没有用了,估计是防止频繁获取短信吧

今天就到这里了,具体代码可以到GitHub下载查看

github代码下载:yiwent

写博客不容易,喜欢希望多给个start,老铁,抱拳了。

上一篇下一篇

猜你喜欢

热点阅读