AsyncHttpClient 登录 Application Fragment 回调 监听 软键盘

时间:2023-03-09 10:03:32
AsyncHttpClient 登录 Application Fragment 回调 监听 软键盘

Activity
AsyncHttpClient 登录 Application Fragment 回调 监听 软键盘
/**登录界面及登陆后用户首页界面,使用两个Fragment实现*/
public class LoginActivity extends Activity implements LoginInterface {
    /** 存放Fragment的容器 */
    private View fragmentContainer;
    /** 在使用replace替换Fragment是需要一个id */
    public static final int ROOT_ID = 0x0011223344;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        fragmentContainer = new ScrollView(this);//可以滚动
        fragmentContainer.setBackgroundColor(0xfffbf7ed);
        fragmentContainer.setId(ROOT_ID);
        setContentView(fragmentContainer);
        LoginFragment loginFragment = new LoginFragment();
        getFragmentManager().beginTransaction().replace(ROOT_ID, loginFragment).commit();
        loginFragment.setLoginInterface(this);//当登录后采用回调方式重新加载用户信息
        //如果进入此Activity时有出入账户密码,则直接登录
        Bundle bundle = getIntent().getExtras();
        if (bundle != null) {
            String account = bundle.getString("account");
            String password = bundle.getString("password");
            loginFragment.login(this, account, password);
        }
    }
    @Override
    /**第三步,让【被调用者】实现此接口,并在实现的方法中自定义自己的回调逻辑*/
    public void loginComplete(boolean isSuccess, String result) {
        MyHeadFragment headFragment = new MyHeadFragment();
        Bundle bundle = new Bundle();
        bundle.putString("result", result);
        bundle.putBoolean("isSuccess", isSuccess);
        headFragment.setArguments(bundle);
        getFragmentManager().beginTransaction().replace(ROOT_ID, headFragment).commitAllowingStateLoss();
        //当使用commit方法时,系统将进行状态判断,如果状态(mStateSaved)已经保存,将发生"Can not perform this action after onSaveInstanceState"错误。
    }
}

Application
/**用于设置全局变量*/
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        mApplication = this;
    }
    private static MyApplication mApplication = null;
    public static MyApplication getApplication() {
        return mApplication;
    }
    private UserBean mUser;
    public UserBean getUser() {
        return mUser;
    }
    public void setUser(UserBean mUser) {
        this.mUser = mUser;
    }
    @Override
    public void onTerminate() {//当终止应用程序对象时调用,不保证一定被调用
        super.onTerminate();
        System.gc();
    }
}

LoginFragment
public class LoginFragment extends Fragment implements OnClickListener, ITextChangeListener, OnLayoutChangeListener {
    private Activity mContext;
    private View root;
    private ImageView iv_close;
    private LinearLayout ll_third_login;
    private RelativeLayout rl_root;
    private RelativeLayout rl_login;
    private TextView tv_qq_login;
    private TextView tv_wechat_login;
    private TextView tv_forget;
    private TextView tv_login;
    private TextView tv_signup;
    private TextView tv_tips;
    private MineLoginEditText et_account;
    private MineLoginEditText et_pass;
    private Rect firstRect; //用于储存开始的可见区域
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mContext = getActivity();
        root = inflater.inflate(R.layout.fragment_login, container, false);
        findViews();
        initViews();
        setOnClickListeners();
        return root;
    }
    //***********************************************************************************************************************************
    //                                                                                                        初始化    
    //***********************************************************************************************************************************
    private void findViews() {
        rl_root = (RelativeLayout) root.findViewById(R.id.rl_root);
        iv_close = (ImageView) root.findViewById(R.id.iv_close);
        ll_third_login = (LinearLayout) root.findViewById(R.id.ll_third_login);
        tv_qq_login = (TextView) root.findViewById(R.id.tv_qq_login);
        tv_wechat_login = (TextView) root.findViewById(R.id.tv_wechat_login);
        rl_login = (RelativeLayout) root.findViewById(R.id.rl_login);
        tv_tips = (TextView) root.findViewById(R.id.tv_tips);
        et_account = (MineLoginEditText) root.findViewById(R.id.et_account);
        et_pass = (MineLoginEditText) root.findViewById(R.id.et_pass);
        tv_forget = et_pass.getTv_forget();
        tv_signup = (TextView) root.findViewById(R.id.tv_signup);
        tv_login = (TextView) root.findViewById(R.id.tv_login);
    }
    private void initViews() {
        et_account.setTextChangeListener(this);
        et_account.getEditText().setHint("请输入账号");
        et_account.getTv_forget().setWidth(0);//若设置setVisibility则后面有可能显示出来了
        et_pass.setTextChangeListener(this);
        et_pass.getEditText().setHint("请输入密码");
        et_pass.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
        rl_root.addOnLayoutChangeListener(this);
        rl_root.post(new Runnable() {
            @Override
            public void run() {
                firstRect = new Rect();
                rl_root.getWindowVisibleDisplayFrame(firstRect);
            }
        });
    }
    private void setOnClickListeners() {
        iv_close.setOnClickListener(this);
        tv_qq_login.setOnClickListener(this);
        tv_wechat_login.setOnClickListener(this);
        tv_signup.setOnClickListener(this);
        tv_login.setOnClickListener(this);
        tv_forget.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.iv_close:
            if (loginInterface != null) loginInterface.loginComplete(false, "这哥们按了关闭按钮,并没有登录");
            break;
        case R.id.tv_login:
            login(mContext, et_account.getEditText().getText().toString().trim(), et_pass.getEditText().getText().toString().trim());
            break;
        case R.id.tv_signup://直接登录
            login(mContext, "103468", "103468");
            break;
        case R.id.tv_qq_login://qq登录
            break;
        case R.id.tv_wechat_login://微信登录
            break;
        case R.id.tv_forget://跳到找回密码界面
            break;
        default:
            break;
        }
    }
    //***********************************************************************************************************************************
    //                                                                                                        登录        
    //***********************************************************************************************************************************
    /**账号密码登录*/
    public void login(final Context mContext, String userAccount, String pass) {
        if (TextUtils.isEmpty(userAccount)) {
            Toast.makeText(mContext, "请输入账号或手机号", Toast.LENGTH_SHORT).show();
            return;
        }
        if (userAccount.length() < 6 || userAccount.length() > 12 || !checkUserName(userAccount)) {
            et_account.getIvClean().setVisibility(View.VISIBLE);
            Toast.makeText(mContext, "账号格式错误,账号为6–12位数字、字母或@的组合", Toast.LENGTH_SHORT).show();
            return;
        }
        if (TextUtils.isEmpty(pass)) {
            Toast.makeText(mContext, "请输入密码", Toast.LENGTH_SHORT).show();
            return;
        }
        if (pass.length() < 6 || pass.length() > 20 || !checkPassword(pass)) {
            et_pass.getIvClean().setVisibility(View.VISIBLE);
            Toast.makeText(mContext, "密码格式错误,请输入6–20位字符(字母,数字或下划线组成)", Toast.LENGTH_SHORT).show();
            return;
        }
        RequestParams params = new RequestParams();
        params.put("user", userAccount);
        params.put("pass", pass);
        params.put("imsi", getImsi(mContext));
        ProgressDialogUtil.showProgressDialog(mContext, "", "登录中...");
        AsyncXiuHttpHelper.post(UrlOfServer.RQ_LOGIN, params, new OnHttpListener<JSONObject>() {
            @Override
            public void onHttpListener(boolean httpSuccessed, JSONObject json) {
                ProgressDialogUtil.dismissProgressDialog();
                if (httpSuccessed) {
                    try {
                        int result = json.getInt("result");
                        if (result == 1) {//请求成功
                            //设置用户信息
                            MyApplication.getApplication().setUser(new UserBean(json));
                            if (loginInterface != null) loginInterface.loginComplete(true, json.toString());//回调
                            Toast.makeText(mContext, "登录成功", Toast.LENGTH_SHORT).show();
                        } else if (result == -1) {
                            tv_tips.setVisibility(View.VISIBLE);
                            if (et_account.getEditText().getText().toString().length() > 0) et_account.getIvClean().setVisibility(View.VISIBLE);
                            if (et_pass.getEditText().getText().toString().length() > 0) et_pass.getIvClean().setVisibility(View.VISIBLE);
                            Toast.makeText(mContext, "账号或密码错误", Toast.LENGTH_SHORT).show();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    Toast.makeText(mContext, "通信失败,请稍候重试", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
    @Override
    public void onTextChange() {
        final String userAccount = et_account.getEditText().getText().toString().trim();
        final String pass = et_pass.getEditText().getText().toString().trim();
        boolean isAccountOk = false;
        boolean isPassOk = false;
        if (userAccount != null && userAccount.length() >= 6 && userAccount.length() <= 12) isAccountOk = true;
        if (pass != null && pass.length() >= 6 && pass.length() <= 20) isPassOk = true;
        if (isAccountOk && isPassOk) tv_login.setTextColor(0xFFFFFFFF);
        else tv_login.setTextColor(0x7FFFFFFF);
    }
    //***********************************************************************************************************************************
    //                                                                                                        回调        
    //***********************************************************************************************************************************
    /**第二步,在【调用者】中定义一个实例,并暴露一个对此实例进行set的方法*/
    private LoginInterface loginInterface;
    public void setLoginInterface(LoginInterface loginInterface) {
        this.loginInterface = loginInterface;
    }
    //***********************************************************************************************************************************
    //                                                                                                        键盘显示与隐藏        
    //***********************************************************************************************************************************
    @Override
    /**Fragment不可见时隐藏软键盘*/
    public void onStop() {
        super.onStop();
        InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(et_account.getWindowToken(), 0);
    }
    @Override
    /**Fragment从Activity中移除时取消监听*/
    public void onDetach() {
        super.onDetach();
        rl_root.removeOnLayoutChangeListener(this);
    }
    @Override
    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
        Rect rect = new Rect();
        rl_root.getWindowVisibleDisplayFrame(rect);
        if (firstRect != null) {
            if (firstRect.height() - rect.height() > 50) softInputShowAnimate();
            else softInputHideAnimate();
        }
    }
    /**键盘弹出时的动画*/
    private void softInputShowAnimate() {
        //既然都隐藏了,就不让点击了
        tv_qq_login.setClickable(false);
        tv_wechat_login.setClickable(false);
        //如果偏移过就不偏移了
        if (Math.abs(rl_login.getTranslationY()) > 0) return;
        int translation_y = mContext.getResources().getInteger(R.integer.anim_translation_y);//也可直接通过dimens文件适配,这样就不用在代码中转换单位了
        float translationY = translation_y * mContext.getResources().getDisplayMetrics().density + 0.5f;//将dp转为px
        ObjectAnimator loginAnimator = ObjectAnimator.ofFloat(rl_login, "translationY", 0, -translationY);
        loginAnimator.setInterpolator(new AccelerateInterpolator());
        ObjectAnimator thirdLoginAnimator = ObjectAnimator.ofFloat(ll_third_login, "alpha", 1, 0);
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playTogether(loginAnimator, thirdLoginAnimator);
        animatorSet.setDuration(400);
        animatorSet.start();
    }
    /**键盘隐藏时的动画*/
    private void softInputHideAnimate() {
        //显示后可以点击
        tv_qq_login.setClickable(true);
        tv_wechat_login.setClickable(true);
        ObjectAnimator loginAnimator = ObjectAnimator.ofFloat(rl_login, "translationY", rl_login.getTranslationY(), 0);
        loginAnimator.setInterpolator(new DecelerateInterpolator());
        ObjectAnimator thirdLoginAnimator = ObjectAnimator.ofFloat(ll_third_login, "alpha", 0, 1);
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playTogether(loginAnimator, thirdLoginAnimator);
        animatorSet.setDuration(400);
        animatorSet.start();
    }
    //***********************************************************************************************************************************
    //                                                                                                            工具方法    
    //***********************************************************************************************************************************
    /**
     * 检查账号,账号为6–12位数字、字母或@的组合      [0-9a-zA-Z@]*
     */
    public static boolean checkUserName(String password) {
        Pattern pattern = Pattern.compile("^[0-9a-zA-Z@]+$"); // [0-9a-zA-Z@]*
        Matcher m = pattern.matcher(password);
        return m.matches();
    }
    /**
     * 检查密码,6–20位字符(字母,数字或下划线组成)     [0-9a-zA-Z_]*
     */
    public static boolean checkPassword(String password) {
        Pattern pattern = Pattern.compile("^[0-9a-zA-Z_]+$"); // [0-9a-zA-Z_]*
        Matcher m = pattern.matcher(password);
        return m.matches();
    }
    /**
     * 获取IMSI。Returns the unique subscriber ID, for example, the IMSI for a GSM phone. Requires Permission: READ_PHONE_STATE
     */
    public static String getImsi(Context context) {
        TelephonyManager iPhoneManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        return iPhoneManager.getSubscriberId();
    }
}

Fragment2
public class MyHeadFragment extends Fragment {
    private Activity mContext;
    private TextView textView;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mContext = getActivity();
        textView = new TextView(mContext);
        textView.setText("用户首页的Fragment");
        textView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                textView.append("\n" + new SimpleDateFormat("yyyy-MM-dd E aHH:mm:ss", Locale.getDefault()).format(new Date()));
            }
        });
        Bundle bundle = getArguments();//从activity传过来的Bundle
        if (bundle != null) {
            boolean isSuccess = bundle.getBoolean("isSuccess");
            String result = bundle.getString("result");
            textView.append("\n是否登录成功" + isSuccess + ":\n" + JsonFormatTool.formatJson(result));
        }
        return textView;
    }
}

EditText
/**
 * 一个简单的EditText,可监听内容变化,有清除内容的功能
 * @author 白乾涛
 */
public class MineLoginEditText extends FrameLayout implements TextWatcher {
    private EditText et;
    private ImageView iv_clean;
    private TextView tv_forget;
    public MineLoginEditText(Context context) {
        super(context);
        initView(context);
    }
    public MineLoginEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView(context);
    }
    public MineLoginEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }
    private void initView(Context context) {
        inflate(context, R.layout.view_login_et, this);
        et = (EditText) findViewById(R.id.et);
        iv_clean = (ImageView) findViewById(R.id.iv_clean);
        tv_forget = (TextView) findViewById(R.id.tv_forget);
        et.addTextChangedListener(this);
        iv_clean.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                et.setText("");
            }
        });
    }
    //监听**************************************************************************************************************************
    private ITextChangeListener mTextChangeListener;
    public interface ITextChangeListener {
        void onTextChange();
    }
    public void setTextChangeListener(ITextChangeListener mTextChangeListener) {
        this.mTextChangeListener = mTextChangeListener;
    }
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }
    @Override
    public void afterTextChanged(Editable s) {
        if (s.length() > 0) {
            iv_clean.setVisibility(View.VISIBLE);
            iv_clean.setImageResource(R.drawable.mine_delete_selector);
        } else iv_clean.setVisibility(View.GONE);
        if (mTextChangeListener != null) mTextChangeListener.onTextChange();
    }
    //get方法**************************************************************************************************************************
    public TextView getTv_forget() {
        return tv_forget;
    }
    public EditText getEditText() {
        return et;
    }
    public ImageView getIvClean() {
        return iv_clean;
    }
}