教育系统APP(四)

“我”的模块
掌握修改密码功能的开发,实现用户密码的修改
掌握设置密保功能的开发,并且通过密保可以找回用户密码

挑战任务
初次打开页面都是Fragment_1,请修改相关代码,让初始打开的页面为Fragment_3,别忘了底部导航栏也要变颜色哦

解决方案
改MainActivity.java即可

package cn.edu.gdmec.android.boxuegu.activity;

import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import cn.edu.gdmec.android.boxuegu.R;
import cn.edu.gdmec.android.boxuegu.fragment.CourseFragment;
import cn.edu.gdmec.android.boxuegu.fragment.ExercisesFragment;
import cn.edu.gdmec.android.boxuegu.fragment.MyinfoFragment;

/*任务在主界面的Hello World位置显示:用户名+“登录成功”*/
public class MainActivity extends FragmentActivity implements View.OnClickListener{
    private RelativeLayout main_body;
    private TextView bottom_bar_text_course;
    private ImageView bottom_bar_image_course;
    private RelativeLayout bottom_bar_course_btn;
    private TextView bottom_bar_text_exercises;
    private ImageView bottom_bar_image_exercises;
    private RelativeLayout bottom_bar_exercises_btn;
    private TextView bottom_bar_text_myinfo;
    private ImageView bottom_bar_image_myinfo;
    private RelativeLayout bottom_bar_myinfo_btn;
    private LinearLayout main_bottom_bar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        //把Fragment加到Activity里的代码如下
       /* FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.add(R.id.main_body,new CourseFragment()).commit();*/
       setMain();
    }

    private void setMain() {
        this.getSupportFragmentManager().beginTransaction().add(R.id.main_body,new MyinfoFragment()).commit();
        setSelectStatus(2);
    }

    private void setSelectStatus(int index) {
        switch (index){
            case 0:
                bottom_bar_image_course.setImageResource(R.drawable.main_course_icon_selected);
                bottom_bar_text_course.setTextColor(Color.parseColor("#0097F7"));
                bottom_bar_text_exercises.setTextColor(Color.parseColor("#666666"));
                bottom_bar_text_myinfo.setTextColor(Color.parseColor("#666666"));
                bottom_bar_image_exercises.setImageResource(R.drawable.main_exercises_icon);
                bottom_bar_image_myinfo.setImageResource(R.drawable.main_my_icon);
                break;
            case 1:
                bottom_bar_image_exercises.setImageResource(R.drawable.main_exercises_icon_selected);
                bottom_bar_text_exercises.setTextColor(Color.parseColor("#0097F7"));
                bottom_bar_text_course.setTextColor(Color.parseColor("#666666"));
                bottom_bar_text_myinfo.setTextColor(Color.parseColor("#666666"));
                bottom_bar_image_course.setImageResource(R.drawable.main_course_icon);
                bottom_bar_image_myinfo.setImageResource(R.drawable.main_my_icon);
                break;
            case 2:
                bottom_bar_image_myinfo.setImageResource(R.drawable.main_my_icon_selected);
                bottom_bar_text_myinfo.setTextColor(Color.parseColor("#0097F7"));
                bottom_bar_text_course.setTextColor(Color.parseColor("#666666"));
                bottom_bar_text_exercises.setTextColor(Color.parseColor("#666666"));
                bottom_bar_image_exercises.setImageResource(R.drawable.main_exercises_icon);
                bottom_bar_image_course.setImageResource(R.drawable.main_course_icon);
                break;
        }
    }
    private void initView() {
        main_body = findViewById(R.id.main_body);
        bottom_bar_text_course = findViewById(R.id.bottom_bar_text_course);
        bottom_bar_image_course = findViewById(R.id.bottom_bar_image_course);
        bottom_bar_course_btn = findViewById(R.id.bottom_bar_course_btn);
        bottom_bar_text_exercises = findViewById(R.id.bottom_bar_text_exercises);
        bottom_bar_image_exercises = findViewById(R.id.bottom_bar_image_exercises);
        bottom_bar_exercises_btn = findViewById(R.id.bottom_bar_exercises_btn);
        bottom_bar_text_myinfo = findViewById(R.id.bottom_bar_text_myinfo);
        bottom_bar_image_myinfo = findViewById(R.id.bottom_bar_image_myinfo);
        bottom_bar_myinfo_btn = findViewById(R.id.bottom_bar_myinfo_btn);
        main_bottom_bar = findViewById(R.id.main_bottom_bar);

        bottom_bar_course_btn.setOnClickListener(this);
        bottom_bar_exercises_btn.setOnClickListener(this);
        bottom_bar_myinfo_btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bottom_bar_course_btn:
                getSupportFragmentManager().beginTransaction().add(R.id.main_body,new CourseFragment()).commit();
                setSelectStatus(0);
                break;
            case R.id.bottom_bar_exercises_btn:
                getSupportFragmentManager().beginTransaction().add(R.id.main_body,new ExercisesFragment()).commit();
                setSelectStatus(1);
                break;
            case R.id.bottom_bar_myinfo_btn:
                getSupportFragmentManager().beginTransaction().add(R.id.main_body,new MyinfoFragment()).commit();
                setSelectStatus(2);
                break;
        }
    }
}

APP(四)
博学谷项目“我”的模块

学习目标
掌握修改密码功能的开发,实现用户密码的修改;
掌握设置密保功能的开发,并且通过密保可以找回用户密码。

项目实操
“我”的界面
设置
修改密码
设置密保和找回密码
任务实施
修复fragment的小BUG
修改密保设置页面
优化找回密码

“我”的模块主要时以设置用户以及保证用户安全为主。当用户登录成功后,可以修改密码以及设置密保,且只有设置过密保的帐户才可以找回密码。

“我”的界面
首先是资源图片,“我”的界面要用到的图片有myinfo_login_bg、course_history_icon、iv_right_arrow、myinfo_setting_icon

老样子,将它们放到drawable下

file

然后是布局代码,在我们上一次课创的fragment_myinfo里加上代码fragment_myinfo.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical">
    <LinearLayout
        android:id="@+id/ll_head"
        android:layout_width="match_parent"
        android:layout_height="240dp"
        android:background="@drawable/myinfo_login_bg"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/iv_head_icon"
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="75dp"
            android:src="@drawable/default_icon" />
        <TextView
            android:id="@+id/tv_user_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="10dp"
            android:text="点击登录"
            android:textColor="@android:color/white"
            android:textSize="16sp" />
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginTop="20dp"
        android:background="#E3E3E3" />
    <RelativeLayout
        android:id="@+id/rl_course_history"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:background="#F7F8F8"
        android:gravity="center_vertical">
        <ImageView
            android:id="@+id/iv_course_history_icon"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_centerVertical="true"
            android:layout_marginLeft="25dp"
            android:src="@drawable/course_history_icon" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="25dp"
            android:layout_toRightOf="@id/iv_course_history_icon"
            android:text="播放记录"
            android:textColor="#A3A3A3"
            android:textSize="16sp" />
        <ImageView
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="25dp"
            android:src="@drawable/iv_right_arrow" />
    </RelativeLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#E3E3E3" />
    <RelativeLayout
        android:id="@+id/rl_setting"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:background="#F7F8F8"
        android:gravity="center_vertical">
        <ImageView
            android:id="@+id/iv_userInfo_icon"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_centerVertical="true"
            android:layout_marginLeft="25dp"
            android:src="@drawable/myinfo_setting_icon" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="25dp"
            android:layout_toRightOf="@id/iv_userInfo_icon"
            android:text="设置"
            android:textColor="#A3A3A3"
            android:textSize="16sp" />
        <ImageView
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="25dp"
            android:src="@drawable/iv_right_arrow" />
    </RelativeLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#E3E3E3" />
</LinearLayout>

修改完成后,我们试着运行一下,点击底部导航栏中的“我”,一个毫无互动的页面就出来啦。

“我”的界面能显示后,我们来写个工具类。
由于项目多次用到sharedPreferences共享参数去存储用户的登录状态或清除登录状态,“我”的界面也要求用到读取用户姓名的方法,所以我们干脆把这三个方法都扔到AnalysisUtils里面吧。
在Utils包中新建一个Java类,名为AnalysisUtils。

创建完成后,我们在里面写上readLoginStatus()、clearLoginStatus()、
readLoginUserName()三个方法。

AnalysisUtils.java

package cn.edu.gdmec.android.boxuegu.utils;

import android.content.Context;
import android.content.SharedPreferences;

public class AnalysisUtils {
    //读取用户名
    public static String readLoginUserName(Context context){
        SharedPreferences sharedPreferences = context.getSharedPreferences("loginInfo",Context.MODE_PRIVATE);
        String userName=sharedPreferences.getString("loginUserName","");
        return userName;
    }

    //读取登录状态
    public static boolean readLoginStatus(Context context){
        SharedPreferences sharedPreferences = context.getSharedPreferences("loginInfo",Context.MODE_PRIVATE);
        boolean isLogin=sharedPreferences.getBoolean("isLogin",false);
        return isLogin;
    }

    //清除登录状态
    public static void cleanLoginStatus(Context context){
        SharedPreferences sharedPreferences = context.getSharedPreferences("loginInfo",Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putBoolean("isLogin",false);
        editor.putString("loginUserName","");
        editor.commit();
    }
}

以后我们要用到这些方法的时候,调用一下就好啦。
写完工具类后,我们来继续完善“我”的页面的代码。
给MyinfoFragment加上View.OnClickListener接口。

public class MyinfoFragment extends Fragment implements View.OnClickListener{

在冒红的地方alt+回车生成onClick()方法,把要响应的id加上去。

MyinfoFragment.java

@Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.ll_head:
                break;
            case R.id.rl_course_history:
                break;
            case R.id.rl_setting:
                break;
        }
    }

别忘了监听器。

MyinfoFragment.java

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        llHead = (LinearLayout) view.findViewById(R.id.ll_head);
        ivHeadIcon = (ImageView) view.findViewById(R.id.iv_head_icon);
        tvUserName = (TextView) view.findViewById(R.id.tv_user_name);
        rlCourseHistory = (RelativeLayout) view.findViewById(R.id.rl_course_history);
        ivCourseHistoryIcon = (ImageView) view.findViewById(R.id.iv_course_history_icon);
        rlSetting = (RelativeLayout) view.findViewById(R.id.rl_setting);
        ivUserInfoIcon = (ImageView) view.findViewById(R.id.iv_userInfo_icon);

        llHead.setOnClickListener(this);
        rlCourseHistory.setOnClickListener(this);
        rlSetting.setOnClickListener(this);
    }

“我”的界面的头像部分,要实现两个功能

打开“我”的界面后要判断是否已登录,已登录显示用户名,未登录显示“点击登陆”。
头像部分点击后,会判断是否登录,如果登录了,则跳转到个人资料界面,如果没登录,则跳转到login页面。
先来完成第一个功能
我们在onViewCreate()里写个if else判断语句,根据当前登录状态来显示同像下相应的文本。
判断的内容就可以调用我们刚才写过的工具类啦。

MyinfoFragment.java

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        llHead = (LinearLayout) view.findViewById(R.id.ll_head);
        ivHeadIcon = (ImageView) view.findViewById(R.id.iv_head_icon);
        tvUserName = (TextView) view.findViewById(R.id.tv_user_name);
        rlCourseHistory = (RelativeLayout) view.findViewById(R.id.rl_course_history);
        ivCourseHistoryIcon = (ImageView) view.findViewById(R.id.iv_course_history_icon);
        rlSetting = (RelativeLayout) view.findViewById(R.id.rl_setting);
        ivUserInfoIcon = (ImageView) view.findViewById(R.id.iv_userInfo_icon);

        if (AnalysisUtils.readLoginStatus(getActivity())){
            tvUserName.setText(AnalysisUtils.readLoginUserName(getActivity()));
        }else {
            tvUserName.setText("点击登录");
        }

        llHead.setOnClickListener(this);
        rlCourseHistory.setOnClickListener(this);
        rlSetting.setOnClickListener(this);
    }

然后在onClick()方法里给头像部分的点击以及其他按钮加上判断。

MyinfoFragment.java

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.ll_head:
                if (AnalysisUtils.readLoginStatus(getActivity())){
                    //跳转到个人资料界面
                }else {
                    //跳转到登录界面
                    Intent intent = new Intent(getActivity(), LoginActivity.class);
                    getActivity().startActivityForResult(intent,1);
                }
                break;
            case R.id.rl_course_history:
                if (AnalysisUtils.readLoginStatus(getActivity())){
                    //跳转到播放记录页面
                }else {
                    Toast.makeText(getActivity(),"您未登录,请先登录",Toast.LENGTH_SHORT).show();
                }
                break;
            case R.id.rl_setting:
                if (AnalysisUtils.readLoginStatus(getActivity())){
                    //跳转到设置界面
                }else {
                    Toast.makeText(getActivity(),"您未登录,请先登录",Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }

注意:未登录时,点击登陆打开登陆页面后,需要MainActivity更新状态并显示,所以用startActivityForResult()方法打开。老样子,这边用startActivityForResult()打开,MainActivity就要加上onActivityForResult()方法来执行响应。

在MainActivity里按ctrl+O,再打“onActivity”几个字母,找到onActivityForResult方法,点击生成代码。

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    }

再给它加上代码:判断从LoginActivity传过来登陆状态,并执行响应动作。

MainActivity.java

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (data!=null){
            boolean isLogin=data.getBooleanExtra("isLogin",false);
            if (isLogin){
                setSelectStatus(0);
            }
            else {
                setSelectStatus(2);
            }
        }
    }

Ok,为了方便检验效果,我们给MainActivity加上退出清除登陆状态的方法。连续点击返回两次则退出,两次点击间隔超过2秒则提示再按一次退出。

MainActivity.java

protected long exitTime; 

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
            if ((System.currentTimeMillis() - exitTime) > 2000) {
                Toast.makeText(MainActivity.this, "再按一次退出博学谷", Toast.LENGTH_SHORT).show();
                exitTime = System.currentTimeMillis();
            } else {
                this.finish();
                if (AnalysisUtils.readLoginStatus(this)) {
                    AnalysisUtils.cleanLoginStatus(this);
                }
                System.exit(0);
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

然后我们运行下程序,登陆完成后,“我”的界面应该显示用户名。
这时候大家会发现,点击“点击登陆”,登陆完成后,显示的是下图的页面,再点一下底部导航栏后,又正常显示了。但是完成上一节任务的会不一样哦~

这就是常见的fragment刷新问题啦,把它当作一个小BUG,做为今天的“任务实施”吧,解决它。

设置
接下来我们来做设置界面。
新建一个布局文件,名为activity_setting。

加上布局代码。
activity_setting.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical">
    <!--这个标题显示 设置-->
    <include layout="@layout/main_title_bar" />
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginTop="15dp"
        android:background="#E3E3E3" />
    <RelativeLayout
        android:id="@+id/rl_modify_psw"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#F7F8F8"
        android:gravity="center_vertical"
        android:paddingLeft="10dp"
        android:paddingRight="10dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="25dp"
            android:text="修改密码"
            android:textColor="#A3A3A3"
            android:textSize="16sp" />
        <ImageView
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:paddingRight="25dp"
            android:src="@drawable/iv_right_arrow" />
    </RelativeLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#E3E3E3" />
    <RelativeLayout
        android:id="@+id/rl_security_setting"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#F7F8F8"
        android:gravity="center_vertical"
        android:paddingLeft="10dp"
        android:paddingRight="10dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="25dp"
            android:text="设置密保"
            android:textColor="#A3A3A3"
            android:textSize="16sp" />
        <ImageView
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:paddingRight="25dp"
            android:src="@drawable/iv_right_arrow" />
    </RelativeLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#E3E3E3" />
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginTop="15dp"
        android:background="#E3E3E3" />
    <RelativeLayout
        android:id="@+id/rl_exit_login"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#F7F8F8"
        android:gravity="center_vertical"
        android:paddingLeft="10dp"
        android:paddingRight="10dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="25dp"
            android:text="退出登录"
            android:textColor="#A3A3A3"
            android:textSize="16sp" />
    </RelativeLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#E3E3E3" />
</LinearLayout>

创建一个新activity
给tv_main_title设个文本。给title_bar加个背景。加上View.onClickListener接口。Alt+回车生成onClick()代码。在onClick()中加上设置界面要用到的几个按钮。给几个按钮加上监听器。

SettingActivity.java

package cn.edu.gdmec.android.boxuegu.activity;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import cn.edu.gdmec.android.boxuegu.R;
import cn.edu.gdmec.android.boxuegu.utils.AnalysisUtils;

public class SettingActivity extends Activity implements View.OnClickListener{
    private TextView tv_back;
    private TextView tv_main_title;
    private TextView tv_save;
    private RelativeLayout title_bar;
    private RelativeLayout rl_modify_psw;
    private RelativeLayout rl_security_setting;
    private RelativeLayout rl_exit_login;
    public static SettingActivity instance=null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_setting);
        instance=this;
        initView();
    }
    private void initView(){
        tv_back=findViewById(R.id.tv_back);
        tv_main_title=findViewById(R.id.tv_main_title);
        tv_save=findViewById(R.id.tv_save);
        title_bar=findViewById(R.id.title_bar);
        rl_modify_psw=findViewById(R.id.rl_modify_psw);
        rl_security_setting=findViewById(R.id.rl_security_setting);
        rl_exit_login=findViewById(R.id.rl_exit_login);

        tv_main_title.setText("设置");
        title_bar.setBackgroundColor(Color.parseColor("#30B4FF"));

        tv_back.setOnClickListener(this);
        rl_modify_psw.setOnClickListener(this);
        rl_security_setting.setOnClickListener(this);
        rl_exit_login.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.tv_back:
                SettingActivity.this.finish();
                break;
            case R.id.rl_modify_psw:
                //修改密码界面
                break;
            case R.id.rl_security_setting:
                //设置密保界面
                break;
            case R.id.rl_exit_login:
                //退出登录,即清除登录状态
                Toast.makeText(this,"退出登录成功",Toast.LENGTH_SHORT).show();
                AnalysisUtils.cleanLoginStatus(this);
                Intent data=new Intent();
                data.putExtra("isLogin",false);
                setResult(RESULT_OK,data);
                finish();
                break;
        }
    }
}

MyinfoFragmrnt.java里把跳转代码加上。

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.ll_head:
                if (AnalysisUtils.readLoginStatus(getActivity())){
                    //跳转到个人资料界面
                }else {
                    //跳转到登录界面
                }
                break;
            case R.id.rl_course_history:
                if (AnalysisUtils.readLoginStatus(getActivity())){
                    //跳转到播放记录页面
                }else {
                    Toast.makeText(getActivity(),"您未登录,请先登录",Toast.LENGTH_SHORT).show();
                }
                break;
            case R.id.rl_setting:
                if (AnalysisUtils.readLoginStatus(getActivity())){
                    //跳转到设置界面
                    Intent intent=new Intent(getActivity(), SettingActivity.class);
                    getActivity().startActivityForResult(intent,1);
                }else {
                    Toast.makeText(getActivity(),"您未登录,请先登录",Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }

别忘了到AndroidManifest.xml声明下SettingActivity,运行程序,在“我”的界面点击设置弹出设置页面。

修改密码
首先是修改密码界面的布局代码
新建一个布局文件,名为activity_modify_psw

直接上代码。
activity_modify_psw.xml

<?xml version="1.0" encoding="utf-8"?>
<!--修改密码-->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/register_bg"
    android:orientation="vertical">
    <include layout="@layout/main_title_bar"/>
    <EditText
        android:id="@+id/et_original_psw"
        android:layout_gravity="center_horizontal"
        android:background="@drawable/register_user_name_bg"
        android:layout_marginTop="35dp"
        android:layout_marginLeft="35dp"
        android:layout_marginRight="35dp"
        android:drawableLeft="@drawable/psw_icon"
        android:drawablePadding="10dp"
        android:gravity="center_vertical"
        android:hint="请输入原始密码"
        android:inputType="textPassword"
        android:paddingLeft="8dp"
        android:textColor="#000000"
        android:textColorHint="#a3a3a3"
        android:textSize="14sp"
        android:singleLine="true"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        />
    <EditText
        android:id="@+id/et_new_psw"
        android:layout_gravity="center_horizontal"
        android:background="@drawable/register_user_name_bg"
        android:layout_marginLeft="35dp"
        android:layout_marginRight="35dp"
        android:drawableLeft="@drawable/psw_icon"
        android:drawablePadding="10dp"
        android:gravity="center_vertical"
        android:hint="请输入新密码"
        android:inputType="textPassword"
        android:paddingLeft="8dp"
        android:textColor="#000000"
        android:textColorHint="#a3a3a3"
        android:textSize="14sp"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        />
    <EditText
        android:id="@+id/et_new_psw_again"
        android:layout_gravity="center_horizontal"
        android:background="@drawable/register_user_name_bg"
        android:layout_marginLeft="35dp"
        android:layout_marginRight="35dp"
        android:drawableLeft="@drawable/psw_icon"
        android:drawablePadding="10dp"
        android:gravity="center_vertical"
        android:hint="请再次输入新密码"
        android:inputType="textPassword"
        android:paddingLeft="8dp"
        android:singleLine="true"
        android:textColor="#000000"
        android:textColorHint="#a3a3a3"
        android:textSize="14sp"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        />
    <Button
        android:id="@+id/btn_save"
        android:layout_gravity="center_horizontal"
        android:textSize="18sp"
        android:textColor="@android:color/white"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginTop="15dp"
        android:layout_marginLeft="35dp"
        android:layout_marginRight="35dp"
        android:background="@drawable/register_selector"
        android:text="保 存"/>
</LinearLayout>

生成activity文件,ModifyPswActivity.java
注意:在submit方法中,密码修改成功之后除了把当前页面关了,还要把设置界面也关了,所以用到instance

package cn.edu.gdmec.android.boxuegu.activity;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import cn.edu.gdmec.android.boxuegu.R;
import cn.edu.gdmec.android.boxuegu.utils.AnalysisUtils;
import cn.edu.gdmec.android.boxuegu.utils.MD5Utils;

public class ModifyPswActivity extends Activity implements View.OnClickListener {
    private TextView tv_back;
    private TextView tv_main_title;
    private TextView tv_save;
    private RelativeLayout title_bar;
    private EditText et_original_psw;
    private EditText et_new_psw;
    private EditText et_new_psw_again;
    private Button btn_save;
    private String userName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_modify_psw);
        initView();
        userName = AnalysisUtils.readLoginUserName(this);
    }

    private void initView() {
        tv_back=findViewById(R.id.tv_back);
        tv_main_title=findViewById(R.id.tv_main_title);
        tv_save=findViewById(R.id.tv_save);
        title_bar=findViewById(R.id.title_bar);
        et_original_psw=findViewById(R.id.et_original_psw);
        et_new_psw=findViewById(R.id.et_new_psw);
        et_new_psw_again=findViewById(R.id.et_new_psw_again);
        btn_save=findViewById(R.id.btn_save);
        tv_main_title.setText("修改密码");
        btn_save.setOnClickListener(this);
        tv_back.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_save:
                submit();
                break;
            case R.id.tv_back:
                finish();
                break;
        }
    }

    private void submit() {
        String psw=et_original_psw.getText().toString().trim();
        String newPsw=et_new_psw.getText().toString().trim();
        String again=et_new_psw_again.getText().toString().trim();
        if (TextUtils.isEmpty(psw)){
            Toast.makeText(this,"请输入原始密码",Toast.LENGTH_SHORT).show();
            return;
        }else if (!MD5Utils.md5(psw).equals(readPsw())){
            Log.i("MD5Utils.md5(psw)",""+MD5Utils.md5(psw));
            Log.i("readPsw",""+readPsw());
            Toast.makeText(this,"输入的密码与原始密码不一致",Toast.LENGTH_SHORT).show();
            return;
        }else if (MD5Utils.md5(newPsw).equals(readPsw())){
            Toast.makeText(this,"输入的新密码与原始密码不能一致",Toast.LENGTH_SHORT).show();
            return;
        }else if (TextUtils.isEmpty(psw)){
            Toast.makeText(this,"请输入密码",Toast.LENGTH_SHORT).show();
            return;
        }else if (TextUtils.isEmpty(again)){
            Toast.makeText(this,"请再次输入新密码",Toast.LENGTH_SHORT).show();
        }else if (!newPsw.equals(again)){
            Toast.makeText(this,"再次输入的新密码不一致",Toast.LENGTH_SHORT).show();
            return;
        }else {
            Toast.makeText(this,"新密码设置成功", Toast.LENGTH_SHORT).show();
            modifyPsw(newPsw);//
            Intent intent=new Intent(ModifyPswActivity.this,LoginActivity.class);
            startActivity(intent);
            //关闭设置页面
            //在submit方法中,密码修改成功之后除了把当前页面关了,还要把设置界面也关了,所以用到instance
            SettingActivity.instance.finish();
            //关闭修改密码页面
            ModifyPswActivity.this.finish();
        }
    }

    private void modifyPsw(String newPsw) {
        String md5psw= MD5Utils.md5(newPsw);
        SharedPreferences sharedPreferences=getSharedPreferences("loginInfo",MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString(userName,md5psw);
        editor.commit();
    }

    private String readPsw() {
        SharedPreferences sharedPreferences=getSharedPreferences("loginInfo",MODE_PRIVATE);
        String spPsw=sharedPreferences.getString(userName,"");
        Log.i("username",userName);
        Log.i("spPsw",spPsw);
        return spPsw;
    }
}

注意:在submit方法中,密码修改成功之后除了把当前页面关了,还要把设置界面也关了,所以用到instance

SettingActivity.java,给它创个instance

SettingActivity.java

public class SettingActivity extends Activity implements View.OnClickListener{
    private TextView tv_back;
    private TextView tv_main_title;
    private TextView tv_save;
    private RelativeLayout title_bar;
    private RelativeLayout rl_modify_psw;
    private RelativeLayout rl_security_setting;
    private RelativeLayout rl_exit_login;
    public static SettingActivity instance=null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_setting);
        instance=this;
        initView();
    }

在onclick()中写上跳转方法。

SettingActivity.java

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.tv_back:
                SettingActivity.this.finish();
                break;
            case R.id.rl_modify_psw:
                //修改密码界面
                Intent intent=new Intent(SettingActivity.this,ModifyPswActivity.class);
                startActivity(intent);
                break;
            case R.id.rl_security_setting:
                //设置密保界面
                break;
            case R.id.rl_exit_login:
                //退出登录,即清除登录状态
                Toast.makeText(this,"退出登录成功",Toast.LENGTH_SHORT).show();
                AnalysisUtils.cleanLoginStatus(this);
                Intent data=new Intent();
                data.putExtra("isLogin",false);
                setResult(RESULT_OK,data);
                finish();
                break;
        }
    }

最后到AndroidManifest.xml声明下activity,运行程序,可看到效果

设置密保和找回密码
设置密保和找回密码页面需要用到的图片资源为
find_psw_icon.png

新建布局文件,名为activity_find_psw。

布局文件的代码:
activity_find_psw.xml

<?xml version="1.0" encoding="utf-8"?>
<!--找回密码-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/login_bg"
    android:orientation="vertical">
    <!--找回密码需要设置标题栏-->
    <include layout="@layout/main_title_bar" />
    <TextView
        android:id="@+id/tv_user_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="35dp"
        android:layout_marginRight="35dp"
        android:layout_marginTop="35dp"
        android:text="您的用户名是?"
        android:textColor="@android:color/white"
        android:textSize="18sp"
        android:visibility="gone" />
    <EditText
        android:id="@+id/et_user_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="35dp"
        android:layout_marginRight="35dp"
        android:layout_marginTop="10dp"
        android:background="@drawable/find_psw_icon"
        android:hint="请输入您的用户名"
        android:inputType="text"
        android:paddingLeft="8dp"
        android:textColor="#000000"
        android:textColorHint="#A3A3A3"
        android:visibility="gone" />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="35dp"
        android:layout_marginRight="35dp"
        android:layout_marginTop="15dp"
        android:text="您的姓名是?"
        android:textColor="@android:color/white"
        android:textSize="18sp"/>
    <EditText
        android:id="@+id/et_validate_name"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:layout_marginLeft="35dp"
        android:layout_marginRight="35dp"
        android:layout_marginTop="10dp"
        android:background="@drawable/find_psw_icon"
        android:hint="请输入要验证的姓名"
        android:inputType="text"
        android:paddingLeft="8dp"
        android:textColor="#000000"
        android:textColorHint="#A3A3A3" />
    <TextView
        android:id="@+id/tv_reset_psw"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="35dp"
        android:layout_marginRight="35dp"
        android:layout_marginTop="15dp"
        android:text="请输入新密码"
        android:textColor="@android:color/white"
        android:textSize="18sp"
        android:visibility="gone"/>
    <Button
        android:id="@+id/btn_validate"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="35dp"
        android:layout_marginRight="35dp"
        android:layout_marginTop="15dp"
        android:background="@drawable/register_selector"
        android:text="验 证"
        android:textColor="@android:color/white"
        android:textSize="18sp" />
</LinearLayout>

生成Activity文件,FindPswActivity.java

FindPswActivity.java

package cn.edu.gdmec.android.boxuegu.activity;

import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import cn.edu.gdmec.android.boxuegu.R;
import cn.edu.gdmec.android.boxuegu.utils.AnalysisUtils;
import cn.edu.gdmec.android.boxuegu.utils.MD5Utils;

public class FindPswActivity extends Activity implements View.OnClickListener {

    private TextView tv_back;
    private TextView tv_main_title;
    private RelativeLayout title_bar;
    private TextView tv_user_name;
    private EditText et_user_name;
    private EditText et_validate_name;
    private TextView tv_reset_psw;
    private Button btn_validate;
    private String from;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_find_psw);
        from=getIntent().getStringExtra("from");
        initView();
    }

    private void initView() {
        tv_back=findViewById(R.id.tv_back);
        tv_main_title=findViewById(R.id.tv_main_title);
        title_bar=findViewById(R.id.title_bar);
        tv_user_name=findViewById(R.id.tv_user_name);
        et_user_name=findViewById(R.id.et_user_name);
        et_validate_name=findViewById(R.id.et_validate_name);
        tv_reset_psw=findViewById(R.id.tv_reset_psw);

        btn_validate=findViewById(R.id.btn_validate);
        if ("security".equals(from)){
            tv_main_title.setText("设置密保");
        }else{
            tv_main_title.setText("找回密码");
            tv_user_name.setVisibility(View.VISIBLE);
            et_user_name.setVisibility(View.VISIBLE);
        }
        tv_back.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FindPswActivity.this.finish();
            }
        });
        btn_validate.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_validate:
                submit();
                break;
        }
    }
    private void submit() {
        // validate
        String validateName = et_validate_name.getText().toString().trim();
        if ("security".equals(from)) {  //设置密保
            if (TextUtils.isEmpty(validateName)) {
                Toast.makeText(this, "请输入要验证的姓名", Toast.LENGTH_SHORT).show();
                return;
            } else {
                Toast.makeText(this, "密保设置成功", Toast.LENGTH_SHORT).show();
                //保存到
                saveSecurity(validateName);
                FindPswActivity.this.finish();
                return;
            }
        }else {
            final String name=et_user_name.getText().toString().trim();
            String sp_security=readSecurity(name);
            if (TextUtils.isEmpty(name)){
                Toast.makeText(this,"请输入您的用户名",Toast.LENGTH_SHORT).show();
                return;
            }else if (!isExistUserName(name)){
                Toast.makeText(this,"您输入的用户名不存在",Toast.LENGTH_SHORT).show();
                return;
            }else if (TextUtils.isEmpty(validateName)){
                Toast.makeText(this,"请输入要验证的姓名",Toast.LENGTH_SHORT).show();
                return;
            }else if (!validateName.equals(sp_security)){
                Toast.makeText(this,"输入的密保不正确",Toast.LENGTH_SHORT).show();
                return;
            }else {
                tv_reset_psw.setVisibility(View.VISIBLE);
                tv_reset_psw.setText("初始密码:123456");
                savePsw(name);
            }
        }
    }
    /**
     * 保存初始化密码
     **/
    private void savePsw(String name) {
        String md5Psw= MD5Utils.md5("123456");
        SharedPreferences sharedPreferences = getSharedPreferences("loginInfo",MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString(name,md5Psw);
        editor.commit();
    }

    private boolean isExistUserName(String name){
        boolean hasUserName=false;
        SharedPreferences sharedPreferences=getSharedPreferences("loginInfo",MODE_PRIVATE);
        String spPsw=sharedPreferences.getString(name,"");
        if (!TextUtils.isEmpty(spPsw)){
            hasUserName=true;
        }
        return hasUserName;
    }
    /**
     * 读取密保
     **/
    private String readSecurity(String name){
        SharedPreferences sharedPreferences=getSharedPreferences("loginInfo",MODE_PRIVATE);
        String security=sharedPreferences.getString(name+"_security","");
        return security;
    }
    /**
     * 保存密保名字
     **/
    private void saveSecurity(String validateName) {
        SharedPreferences sharedPreferences=getSharedPreferences("loginInfo",MODE_PRIVATE);
        SharedPreferences.Editor editor=sharedPreferences.edit();
        editor.putString(AnalysisUtils.readLoginUserName(this)+"_security",validateName);
        editor.commit();
    }
}

把找回密码和设置密保都放在一个Activity里了,所以我们要到登录界面和设置界面添加跳转方法。
到LoginActivity的init()方法里找到tv_find_psw.setOnClickListener。

LoginActivity.java

        //找回密码控件的点击事件
        tv_find_psw.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //跳转到找回密码界面(此页面暂未创建)
                Intent intent=new Intent(LoginActivity.this,FindPswActivity.class);
                startActivity(intent);
            }
        });

SettingActivity的onClick()方法里添加跳转代码

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.tv_back:
                SettingActivity.this.finish();
                break;
            case R.id.rl_modify_psw:
                //修改密码界面
                Intent intent=new Intent(SettingActivity.this,ModifyPswActivity.class);
                startActivity(intent);
                break;
            case R.id.rl_security_setting:
                //设置密保界面
                Intent intent1=new Intent(SettingActivity.this,FindPswActivity.class);
                intent1.putExtra("from","security");
                startActivity(intent1);
                break;
            case R.id.rl_exit_login:
                //退出登录,即清除登录状态
                Toast.makeText(this,"退出登录成功",Toast.LENGTH_SHORT).show();
                AnalysisUtils.cleanLoginStatus(this);
                Intent data=new Intent();
                data.putExtra("isLogin",false);
                setResult(RESULT_OK,data);
                finish();
                break;
        }
    }

最后到AndroidManifest.xml声明下activity

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.edu.gdmec.android.boxuegu">

    <!--原为android:theme="@style/AppTheme"-->
    <!--去除ActionBar标题栏-->
    <!--添加应用图标,app_icon-->
    <application
        android:allowBackup="true"
        android:icon="@drawable/app_icon"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat.NoActionBar">
        <activity android:name=".activity.SplashActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!--添加实现类-->
        <activity android:name=".activity.MainActivity"></activity>
        <activity android:name=".activity.LoginActivity"></activity>
        <activity android:name=".activity.RegisterActivity"></activity>
        <activity android:name=".activity.SettingActivity"></activity>
        <activity android:name=".activity.ModifyPswActivity"></activity>
        <activity android:name=".activity.FindPswActivity"></activity>
    </application>
</manifest>

任务实施
修复fragment的小BUG
在未登录状态下,点击“点击登陆”,登陆完成后,应该显示“我”的界面,并且正常显示用户名。

在登陆状态下,点击“设置”->点击退出登录,应该继续显示“我”的界面,并且正常显示用户名。

修改密保设置页面
密保设置页面的按钮显示的是“验证”,这里应该是“设置”比较合理。
把按钮上的文字改成“设置”,要求修改密码界面按钮依然是“验证”。

优化找回密码
登陆界面的找回密码功能用的是初始化密码,要求改成设置新密码。
注意:显示设置新密码框时,按钮的文字也要变化哦!

更改后的效果:

file

总结
这是走好Android的四步!

❤️ 不要忘记留下你学习的脚印 [点赞 + 收藏 + 评论]

作者Info:

【作者】:Jeskson
【原创公众号】:达达前端小酒馆。
【福利】:公众号回复 “资料” 送自学资料大礼包(进群分享,想要啥就说哈,看我有没有)!
【转载说明】:转载请说明出处,谢谢合作!~

大前端开发,定位前端开发技术栈博客,PHP后台知识点,web全栈技术领域,数据结构与算法、网络原理等通俗易懂的呈现给小伙伴。谢谢支持,承蒙厚爱!!!


若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。


请点赞!因为你们的赞同/鼓励是我写作的最大动力!

欢迎关注达达的CSDN!

这是一个有质量,有态度的博客

前端技术栈

Image placeholder
zhinuo
未设置
  26人点赞

没有讨论,发表一下自己的看法吧

推荐文章
教育系统APP(三)

挑战任务回顾教育系统APP(二)以及教育系统APP(三)检验登录和注册模块。请修改MainActivity和LoginActivity,欢迎界面调转入主界面后,自动跳转入登录界面,登录成功后,返回主界

天翼云赋能教育行业 轻松打造数字化教育平台

2018年4月,教育部印发《教育信息化2.0行动计划》,提出要提高信息化应用水平、提高师生信息素养,建设一个”互联网+教育”大平台,从而构建”互联网+”条件下的人才培养新模式,发展基于互联网的教育服务

学习猿地开创IT教育2.0模式

传统的学习方式都是进入班级,跟着老师面对面的学习。需要有几个硬性条件,就是在固定场地,并且在固定的时间里,按照老师安排的进度学习。基础不一样进度没办法调整、学习不好的跟不上会一直学习不好、有事旷课课程

IT教育培训机构靠谱的怎么选?

  靠谱的IT教育培训机构一定办学历史悠久,课程体系经过长期优化沉淀,知识点新颖紧跟前沿技术发展,有相关部门监督并且审核通过后颁发培训教学资质,这样的机构不可能存在教学质量不佳跑路或者换壳经营的风险。

游戏之外网龙的教育生意经

提起网龙可能最先想到的是游戏,教育市场也有它一席之地,近两年教育业务已经贡献了其一半以上营收。根据财报,2018年网龙教育业务的收入25.66亿元,占本集团总收入的50.9%,同比增长21.9%。网龙

大数据推动教育产业创新发展

《大数据时代》作者维克托•迈尔-舍恩伯格教授著作《与大数据同行:学习和教育的未来》一书指出:当下大数据正悄悄影响到教育体系的每个层面,对于全世界的学习与教育活动,都会产生极为深远的影响。AI辅助教学,

《从PPTV网络视频,到PPIO区块链分布式存储》

摘要:2019年11月26日,同济创业谷与PPIOCodeTalks联合举办了《创新X-区块链与创新创业》区块链技术分享会,本期我们为读者带来主题分享--《从PPTV网络视频,到PPIO区块链分布式存

Pandas数据处理三板斧——map、apply、applymap详解

微信公众号:「Python读财」如有问题或建议,请公众号留言在日常的数据处理中,经常会对一个DataFrame进行逐行、逐列和逐元素的操作,对应这些操作,Pandas中的map、apply和apply

GoWeb教程_14.6. pprof 支持

Go语言有一个非常棒的设计就是标准库里面带有代码的性能监控工具,在两个地方有包: net/http/pprof runtime/pprof 其实net/http/pprof中只是使用runtime

IOS APP开发需要学什么知识和技能?

IOSAPP开发需求学什么学问和技艺?目前IOS系统的APP和Android系统的APP,是手机APP开发的两大主流。就拿IOS系统的APP开发来说,需求和安卓完整不同的开发言语和工具。本文着重来讨论

PPT 分享:《10 个 Go Web 开发框架对比》

在SpeakerDeck上发现一个不错的PPT分享给大家。 原链接:https://speakerdeck.com/fedir/comparison-o... 百度盘链接:https://pan.ba

写了一款 iOS App: 足迹中国 - 统计出行省市,生成各省和全国的旅行地图

说具体功能之前,先放一下下载链接:https://apps.apple.com/cn/app/id1482250279功能地图轮廓截取旅行照片,并可分享 统计你去过中国的多少个省,多少个市 将截取的市

pptx 批量操作幻灯片

本文示例使用python-pptx模块批量生成幻灯片,批量修改导入幻灯片表格内容及格式,以及在指定页插入表格 前言一个prs对象就是一棵树,它的下面挂载了多张幻灯片slide,而每张幻灯片下有多个s

SACC 2019:云闪付APP架构优化实践之路

中国银联科技事业部架构师 程朝程朝2011年加入中国银联,拥有三年应用开发设计经验,三年MySQL与Redis内核开发设计经验,三年应用架构设计经验;擅长分布式系统设计,有丰富的系统设计与调优经验,现

(PPT 下载,来了!)DTCC2019 中国数据库技术大会见证实录

2019年5月8日-10日,DTCC2019第十届中国数据库技术大会历时3天,圆满收官。作为国内顶级的数据领域技术盛会,共有23个技术场次,邀请超过125名专家,包括来自阿里、京东、苏宁、滴滴出行、百

张小龙:用停留时长衡量一个APP的好坏是错误的!

“这两年,业界目标变成所有APP应该尽可能多地去抓住用户的停留时长,这违背常识。一个用户每天的时间是有限的,技术的使命应该是帮助人类提高效率而不是降低效率。”这是张小龙在微信之夜上的一段讲话。1月9日

是什么能让 APP 快速精准定位到我们的位置?

本文作者:smallyang,腾讯IEG开发工程师什么是geohash?它的原理是什么?它帮助我们解决了哪些痛点,本文为你娓娓道来。本文包含以下内容,阅读完需要约10分钟:我们日常生活中遇到哪些定位的

Android篇 | 爱奇艺App启动优化实践分享

导读性能优化一直都是各个APP推进中的重点、难点,爱奇艺App也不例外。在此之前,爱奇艺AppAndroid版的启动速度虽然一直处于同类App领先的水平,但优势距离其他同类的APP距离一直很小。面

app.vue有什么作用?

app.vue可以当做是网站首页,也可以写所有页面中共同需要的动画或者样式,不在他上面写代码也可以。只要你在router文件夹中的index.js填写好路由就ok对应index.html,你也可以改,

app.vue是什么文件?

app.vue是vue页面资源的首加载项,是主组件,页面入口文件,所有页面都是在App.vue下进行切换的;也是整个项目的关键,app.vue负责构建定义及页面组件归集。 exportde

盗版12306骗3000万人下载,暴利高仿App是如何花式捞钱的?

眼看着春运一天一天临近,我按捺不住激动的心情,准备加入抢票大军。可是,当我在应用商城搜索12306时,却发现一大批“12306”。这些App下载量从几万到几千万(未标“官方版”的累计下载量超一千万),

如何使用react做安卓app

如何使用react做安卓app一、首先,我们先创建一个react项目作为演示。1.全局安装create-react-app#全局安装 npminstall-gcreate-react-app2.构建一

app.vue组件如何按需加载?

app.vue组件如何按需加载?按需加载组件,或者异步组件,主要是应用了component的is属性1、template中的代码:这里的每一个按钮,都要显示不同的组件,所以我让他们使用了同一个方法名

app.vue的作用是什么?

app.vue的作用是什么?app.vue可以当做是网站首页,是一个vue项目的主组件,页面入口文件,所有页面都是在App.vue下进行切换的。是整个项目的关键,app.vue负责构建定义及页面组件归

create-react-app兼容ie11配置

今天闲来无事折腾一下create-react-app,发现主流浏览器都没有问题。但是ie11却一直报错,真是倔强的很啊。我翻了下create-react-app的文档,从中看到了正好有对ie9、ie1

{