正式版1.2版

优化:列表新增分割线
优化:替换清空按钮
优化:修改指纹认证流程
This commit is contained in:
Yutousama 2021-08-16 09:38:28 +08:00
parent ac900e5647
commit d305c7809c
11 changed files with 199 additions and 128 deletions

View File

@ -25,7 +25,7 @@ android {
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 30 targetSdkVersion 30
versionCode 1 versionCode 1
versionName "1.1" versionName "1.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
signingConfig signingConfigs.yutou signingConfig signingConfigs.yutou

View File

@ -27,6 +27,7 @@ import com.yutou.passmanage.Datas.ToolsPasswordDao;
import com.yutou.passmanage.Interfaces.NetworkInterface; import com.yutou.passmanage.Interfaces.NetworkInterface;
import com.yutou.passmanage.R; import com.yutou.passmanage.R;
import com.yutou.passmanage.Tools.NetworkTool; import com.yutou.passmanage.Tools.NetworkTool;
import com.yutou.passmanage.Tools.ResTools;
import com.yutou.passmanage.Tools.RoomDatabaseManager; import com.yutou.passmanage.Tools.RoomDatabaseManager;
import java.util.List; import java.util.List;
@ -54,26 +55,27 @@ public class PassWordListAdapter extends RecyclerView.Adapter<PassWordListAdapte
return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.recycler_list, parent, false)); return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.recycler_list, parent, false));
} }
@SuppressLint("SetTextI18n")
@Override @Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
ToolsPassword data = list.get(position); ToolsPassword data = list.get(holder.getAdapterPosition());
String account=ResTools.getString(context,R.string.account)+":"+ data.getAccount();
String password=ResTools.getString(context,R.string.password)+":"+data.getPassword();
holder.name.setText(data.getTitle()); holder.name.setText(data.getTitle());
holder.user.setText("账号:" + data.getAccount()); holder.user.setText(account);
holder.password.setText("密码:" + data.getPassword()); holder.password.setText(password);
holder.copy.setOnClickListener(new View.OnClickListener() { holder.copy.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("simple text", data.getPassword()); ClipData clip = ClipData.newPlainText("", data.getPassword());
clipboard.setPrimaryClip(clip); clipboard.setPrimaryClip(clip);
Toast.makeText(context, "已复制密码", Toast.LENGTH_LONG).show(); Toast.makeText(context, ResTools.getString(context,R.string.toast_copy_password), Toast.LENGTH_LONG).show();
} }
}); });
holder.item_layout.setOnClickListener(new View.OnClickListener() { holder.item_layout.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
showDialog(data, position); showDialog(data, holder.getAdapterPosition());
} }
}); });
@ -178,7 +180,7 @@ public class PassWordListAdapter extends RecyclerView.Adapter<PassWordListAdapte
handler.post(new Runnable() { handler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
Toast.makeText(context, "更新成功", Toast.LENGTH_LONG).show(); Toast.makeText(context, ResTools.getString(context,R.string.toast_update), Toast.LENGTH_LONG).show();
notifyDataSetChanged(); notifyDataSetChanged();
} }
}); });

View File

@ -10,6 +10,8 @@ import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
@ -42,10 +44,11 @@ import static com.yutou.passmanage.Tools.RoomDatabaseManager.addPassword;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
EditText search; EditText search;
ImageButton clearSearch; ImageView clearSearch;
RecyclerView passList; RecyclerView passList;
FloatingActionButton floatButton; FloatingActionButton floatButton;
PassWordListAdapter adapter; PassWordListAdapter adapter;
TextView authError;
Handler handler = new Handler(Looper.getMainLooper()); Handler handler = new Handler(Looper.getMainLooper());
@Override @Override
@ -53,27 +56,24 @@ public class MainActivity extends AppCompatActivity {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
initView();
auth(); auth();
} }
BiometricPrompt prompt; BiometricPrompt prompt;
void auth() { void auth() {
BiometricManager manager = BiometricManager.from(this); BiometricManager manager = BiometricManager.from(this);
if (manager.canAuthenticate(BIOMETRIC_WEAK | DEVICE_CREDENTIAL) == BiometricManager.BIOMETRIC_SUCCESS) { if (manager.canAuthenticate(BIOMETRIC_WEAK | DEVICE_CREDENTIAL) == BiometricManager.BIOMETRIC_SUCCESS) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
/* Intent enrollIntent = new Intent(Settings.ACTION_BIOMETRIC_ENROLL);
enrollIntent.putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
BIOMETRIC_STRONG | DEVICE_CREDENTIAL);
startActivityForResult(enrollIntent, 233);*/
} prompt = new BiometricPrompt(this, ContextCompat.getMainExecutor(this), new BiometricPrompt.AuthenticationCallback() {
prompt=new BiometricPrompt(this, ContextCompat.getMainExecutor(this), new BiometricPrompt.AuthenticationCallback() {
@Override @Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) { public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result); super.onAuthenticationSucceeded(result);
Toast.makeText(MainActivity.this, "验证成功", Toast.LENGTH_LONG).show(); Toast.makeText(MainActivity.this, "验证成功", Toast.LENGTH_LONG).show();
initView();
init(); init();
authError.setVisibility(View.GONE);
passList.setVisibility(View.VISIBLE);
} }
@Override @Override
@ -87,9 +87,11 @@ public class MainActivity extends AppCompatActivity {
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) { public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString); super.onAuthenticationError(errorCode, errString);
System.out.println("errorCode = " + errorCode + ", errString = " + errString); System.out.println("errorCode = " + errorCode + ", errString = " + errString);
if(errorCode==10){ if (errorCode == 10) {
auth(); authError.setText("未授权,点击授权");
}else if(errorCode==13){ authError.setVisibility(View.VISIBLE);
passList.setVisibility(View.GONE);
} else if (errorCode == 13) {
} }
} }
@ -106,7 +108,8 @@ public class MainActivity extends AppCompatActivity {
Toast.makeText(this, "必须在支持指纹的设备上使用", Toast.LENGTH_LONG).show(); Toast.makeText(this, "必须在支持指纹的设备上使用", Toast.LENGTH_LONG).show();
} }
} }
void exit(){
void exit() {
MainActivity.this.finish(); MainActivity.this.finish();
System.exit(0); System.exit(0);
} }
@ -115,6 +118,7 @@ public class MainActivity extends AppCompatActivity {
dao = RoomDatabaseManager.build(this).passwordDao(); dao = RoomDatabaseManager.build(this).passwordDao();
adapter = new PassWordListAdapter(this, new ArrayList<>()); adapter = new PassWordListAdapter(this, new ArrayList<>());
search = findViewById(R.id.search); search = findViewById(R.id.search);
authError = findViewById(R.id.goneText);
clearSearch = findViewById(R.id.clearSearch); clearSearch = findViewById(R.id.clearSearch);
passList = findViewById(R.id.passList); passList = findViewById(R.id.passList);
floatButton = findViewById(R.id.floatButton); floatButton = findViewById(R.id.floatButton);
@ -125,7 +129,12 @@ public class MainActivity extends AppCompatActivity {
search.setText(""); search.setText("");
new Thread(this::showData).start(); new Thread(this::showData).start();
}); });
authError.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
auth();
}
});
search.addTextChangedListener(new TextWatcher() { search.addTextChangedListener(new TextWatcher() {
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@ -157,16 +166,16 @@ public class MainActivity extends AppCompatActivity {
void showAddPasswordDialog() { void showAddPasswordDialog() {
View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.dialog_add_passworld, null); View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.dialog_add_passworld, null);
EditText title, account, password,info; EditText title, account, password, info;
title = view.findViewById(R.id.title); title = view.findViewById(R.id.title);
account = view.findViewById(R.id.account); account = view.findViewById(R.id.account);
password = view.findViewById(R.id.myPassword); password = view.findViewById(R.id.myPassword);
info=view.findViewById(R.id.info); info = view.findViewById(R.id.info);
AlertDialog dialog = new AlertDialog.Builder(MainActivity.this) AlertDialog dialog = new AlertDialog.Builder(MainActivity.this)
.setTitle("添加账号") .setTitle("添加账号")
.setView(view) .setView(view)
.setPositiveButton("保存", (dialog1, which) -> { .setPositiveButton("保存", (dialog1, which) -> {
addPassword(title.getText().toString(), account.getText().toString(), password.getText().toString(), info.getText().toString(),-1, true, new NetworkInterface() { addPassword(title.getText().toString(), account.getText().toString(), password.getText().toString(), info.getText().toString(), -1, true, new NetworkInterface() {
@Override @Override
public void httpGetData(Object data, int state) { public void httpGetData(Object data, int state) {
addDatabase(title.getText().toString(), addDatabase(title.getText().toString(),
@ -234,71 +243,77 @@ public class MainActivity extends AppCompatActivity {
void initData() { void initData() {
new Thread(() -> { new Thread(() -> {
List<ToolsPassword> list = dao.getAllAndRemove(); List<ToolsPassword> list = dao.getAllAndRemove();
for (ToolsPassword password : list) { if (list.size() == 0) {
if (!password.isUpload() && !password.isRemove()) { authError.setText("列表为空,点击右下角+新增配置");
addPassword(password.getTitle(), password.getAccount(), password.getPassword(),password.getInfo(), -1, true, new NetworkInterface() { authError.setVisibility(View.VISIBLE);
@Override passList.setVisibility(View.GONE);
public void httpGetData(Object data, int state) { } else {
new Thread(() -> { for (ToolsPassword password : list) {
password.setUpload(true); if (!password.isUpload() && !password.isRemove()) {
dao.update(password); addPassword(password.getTitle(), password.getAccount(), password.getPassword(), password.getInfo(), -1, true, new NetworkInterface() {
}).start(); @Override
public void httpGetData(Object data, int state) {
new Thread(() -> {
password.setUpload(true);
dao.update(password);
}).start();
} }
@Override @Override
public void httpError(Exception e) { public void httpError(Exception e) {
} }
}); });
} else if (password.isRemove()) { } else if (password.isRemove()) {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
json.put("id", password.getId()); json.put("id", password.getId());
NetworkTool.httpPost(NetworkTool.NetworkAPI.PASSWORD_REMOVE, json, new NetworkInterface() { NetworkTool.httpPost(NetworkTool.NetworkAPI.PASSWORD_REMOVE, json, new NetworkInterface() {
@Override @Override
public void httpGetData(Object data, int state) { public void httpGetData(Object data, int state) {
remove(false); remove(false);
} }
@Override @Override
public void httpError(Exception e) { public void httpError(Exception e) {
remove(true); remove(true);
} }
void remove(boolean isError) { void remove(boolean isError) {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (isError) { if (isError) {
if (password.isUpload()) { if (password.isUpload()) {
password.setRemove(true); password.setRemove(true);
dao.update(password); dao.update(password);
} else {
dao.delete(password);
}
} else { } else {
dao.delete(password); dao.delete(password);
} }
} else { showData();
dao.delete(password);
} }
showData(); }).start();
}
}).start();
} }
}); });
}
} }
} }
NetworkTool.httpGet(NetworkTool.NetworkAPI.PASSWORD_ALL, new JSONObject(), new NetworkInterface() { NetworkTool.httpGet(NetworkTool.NetworkAPI.PASSWORD_ALL, new JSONObject(), new NetworkInterface() {
@Override @Override
public void httpGetData(Object data, int state) { public void httpGetData(Object data, int state) {
data=((String)data).replace("desc","info"); data = ((String) data).replace("desc", "info");
JSONObject json = JSONObject.parseObject((String) data); JSONObject json = JSONObject.parseObject((String) data);
if (json.getInteger("code") == 0) { if (json.getInteger("code") == 0) {
List<ToolsPassword> list = JSONArray.parseArray(json.getJSONArray("data").toJSONString(), ToolsPassword.class); List<ToolsPassword> list = JSONArray.parseArray(json.getJSONArray("data").toJSONString(), ToolsPassword.class);
new Thread(() -> { new Thread(() -> {
try { try {
for (ToolsPassword password : list) { for (ToolsPassword password : list) {
if (dao.isExist(password.getTitle(), password.getAccount(), password.getPassword(),password.getInfo()) == null) { if (dao.isExist(password.getTitle(), password.getAccount(), password.getPassword(), password.getInfo()) == null) {
password.setUpload(true); password.setUpload(true);
dao.insert(password); dao.insert(password);
} }
@ -307,7 +322,7 @@ public class MainActivity extends AppCompatActivity {
e.printStackTrace(); e.printStackTrace();
dao.clear(); dao.clear();
for (ToolsPassword password : list) { for (ToolsPassword password : list) {
if (dao.isExist(password.getTitle(), password.getAccount(), password.getPassword(),password.getInfo()) == null) { if (dao.isExist(password.getTitle(), password.getAccount(), password.getPassword(), password.getInfo()) == null) {
password.setUpload(true); password.setUpload(true);
dao.insert(password); dao.insert(password);
} }

View File

@ -0,0 +1,9 @@
package com.yutou.passmanage.Tools;
import android.content.Context;
public class ResTools {
public static String getString(Context context,int id){
return context.getResources().getString(id);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

View File

@ -18,12 +18,14 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<ImageButton <ImageView
android:id="@+id/clearSearch" android:id="@+id/clearSearch"
android:layout_width="40dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:src="@android:drawable/btn_dialog" android:layout_marginTop="8dp"
android:text="X" android:layout_marginEnd="8dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_close"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@ -36,9 +38,20 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/search" > app:layout_constraintTop_toBottomOf="@+id/search" >
</androidx.recyclerview.widget.RecyclerView> </androidx.recyclerview.widget.RecyclerView>
<TextView
android:id="@+id/goneText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text=""
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/floatButton" android:id="@+id/floatButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -46,6 +59,7 @@
android:layout_marginEnd="32dp" android:layout_marginEnd="32dp"
android:layout_marginBottom="32dp" android:layout_marginBottom="32dp"
android:clickable="true" android:clickable="true"
android:contentDescription="add"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@android:drawable/ic_input_add" /> app:srcCompat="@android:drawable/ic_input_add" />

View File

@ -1,8 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginEnd="15dp"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
@ -16,7 +18,7 @@
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginStart="20dp" android:layout_marginStart="20dp"
android:layout_weight="1" android:layout_weight="1"
android:text="名字" /> android:text="@string/account" />
<EditText <EditText
android:id="@+id/title" android:id="@+id/title"
@ -25,7 +27,7 @@
android:layout_weight="1" android:layout_weight="1"
android:ems="10" android:ems="10"
android:inputType="textPersonName" android:inputType="textPersonName"
android:hint="软件名字" /> android:hint="@string/account" />
</LinearLayout> </LinearLayout>
@ -40,16 +42,17 @@
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginStart="20dp" android:layout_marginStart="20dp"
android:layout_weight="1" android:layout_weight="1"
android:text="账号" /> android:text="@string/account" />
<EditText <EditText
android:id="@+id/account" android:id="@+id/account"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="@dimen/edit_layout_height"
android:layout_weight="1" android:layout_weight="1"
android:ems="10" android:ems="10"
android:inputType="textPersonName" android:inputType="textPersonName"
android:hint="账号" /> android:hint="@string/account"
android:autofillHints="name" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -62,22 +65,26 @@
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginStart="20dp" android:layout_marginStart="20dp"
android:layout_weight="1" android:layout_weight="1"
android:text="密码" /> android:text="@string/password" />
<EditText <EditText
android:id="@+id/myPassword" android:id="@+id/myPassword"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="@dimen/edit_layout_height"
android:layout_weight="1" android:layout_weight="1"
android:ems="10" android:ems="10"
android:hint="密码" /> android:hint="@string/password"
android:autofillHints="name"
android:inputType="textPersonName"
/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="0dp"
android:layout_weight="1" android:layout_weight="1"
android:layout_marginTop="5dp"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
@ -85,13 +92,14 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="20dp" android:layout_marginStart="20dp"
android:text="备注" /> android:text="@string/info" />
<EditText <EditText
android:id="@+id/info" android:id="@+id/info"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ems="10" android:ems="10"
android:layout_marginStart="10dp"
android:gravity="start|top" android:gravity="start|top"
android:hint="这里可以填写备注信息" android:hint="这里可以填写备注信息"
android:inputType="textMultiLine" android:inputType="textMultiLine"

View File

@ -5,56 +5,69 @@
android:id="@+id/item_layout" android:id="@+id/item_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="10dp" android:orientation="vertical">
android:orientation="horizontal">
<ImageButton
android:id="@+id/icon"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_weight="0"
app:srcCompat="@drawable/ic_launcher_foreground"
android:visibility="gone" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
android:layout_weight="2" android:orientation="horizontal">
android:orientation="vertical">
<TextView <ImageButton
android:id="@+id/name" android:id="@+id/icon"
android:layout_width="match_parent" android:layout_width="60dp"
android:layout_height="wrap_content" android:layout_height="60dp"
android:text="TextView" android:layout_weight="0"
android:textSize="16sp" android:visibility="gone"
android:textStyle="bold" /> app:srcCompat="@drawable/ic_launcher_foreground" />
<TextView <LinearLayout
android:id="@+id/user"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:layout_gravity="center|start" android:layout_gravity="center"
android:gravity="right" android:layout_marginStart="10dp"
android:text="TextView" /> android:layout_marginEnd="10dp"
android:layout_weight="2"
android:orientation="vertical">
<TextView <TextView
android:id="@+id/password" android:id="@+id/name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="start|center" android:text="TextView"
android:gravity="right" android:textSize="16sp"
android:text="TextView" /> android:textStyle="bold" />
<TextView
android:id="@+id/user"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|start"
android:gravity="right"
android:text="TextView" />
<TextView
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|center"
android:gravity="right"
android:text="TextView" />
</LinearLayout>
<Button
android:id="@+id/copy"
android:layout_width="70dp"
android:layout_height="60dp"
android:layout_weight="0.1"
android:text="复制" />
</LinearLayout> </LinearLayout>
<Button <View
android:id="@+id/copy" android:id="@+id/divider2"
android:layout_width="60dp" android:layout_width="match_parent"
android:layout_height="60dp" android:layout_height="1dp"
android:layout_weight="0.1" android:background="?android:attr/listDivider" />
android:text="复制" />
</LinearLayout> </LinearLayout>

View File

@ -1,3 +1,9 @@
<resources> <resources>
<string name="app_name">密码管理器</string> <string name="app_name">密码管理器</string>
<string name="password">密码</string>
<string name="account">账号</string>
<string name="info">备注</string>
<string name="name">名字</string>
<string name="toast_copy_password">已复制密码</string>
<string name="toast_update">更新成功</string>
</resources> </resources>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="edit_layout_height">48dp</dimen>
</resources>

View File

@ -5,7 +5,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.2.1' classpath 'com.android.tools.build:gradle:7.0.0'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files