Android studio course design development implementation - Diary APP
Article Directory
foreword
Hello, I am oy, introducing a simple diary APP.
1. Effect
1. Start page, guide page and login registration
2. Diary related functions
3. Personal center interface
2. Function introduction
1. Main functions
- Implement the application startup page and guide page
- Realize setting a password to enter the APP, and encrypt the password
- Realize the bottom navigation bar, divided into diary list, new diary, personal center module
- Realize the basic functions of deleting, modifying and adding to the diary
- Realize a round avatar, set the avatar through the photo album and take pictures and crop the picture. Can be saved in real time.
- Realize network update personal center beauty map.
- Display and close the password, jump to the application setting interface
- Dynamically obtain photo and album access permissions
...
...
2. Knowledge points involved
- Activity and fragment data transfer, page update, and mutual jump.
- SharedPrefrenced storage, file storage, file encryption.
- Android application permission acquisition and setting
- Use of controls: Button, EditText, AlertDialog, Imageview, ImageButton, viewPager2, Toolbar, RecycleView, NavigationButton, etc.
- Use of layout: LinearLayout, ConstraintLayout, RelativeLayout, etc.
- Call the Android system application
- Custom View: Bottom pop-up window (complex), circular avatar
- Glide framework use: network loading pictures
- Android Framework: MVC
…
3. Implementation ideas
- MainActivity is implemented using BottomNavigationView, ViewPager2, and Toolbar.
public class MainActivity extends AppCompatActivity {
private BottomNavigationView bottomNavigationView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initToolbar();
initFragment();
initNavigationBottom();
}
@SuppressLint("ResourceAsColor")
private void initNavigationBottom() {
bottomNavigationView = findViewById(R.id.navigation_bottom);
bottomNavigationView.setItemIconTintList(null);
bottomNavigationView.setOnNavigationItemSelectedListener(itemSelectedListener);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
private void initFragment() {
DiariesFragment diariesFragment = getDiariesFragment();
if (diariesFragment == null) {
diariesFragment = new DiariesFragment();
ActivityUtils.addFragmentToActivity(getSupportFragmentManager(), diariesFragment, R.id.content);
}
}
private DiariesFragment getDiariesFragment() {
return (DiariesFragment) getSupportFragmentManager().findFragmentById(R.id.content);
}
private void initToolbar() {
//设置顶部状态栏为透明
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
private final BottomNavigationView.OnNavigationItemSelectedListener itemSelectedListener = item -> {
switch (item.getItemId()) {
case R.id.menu_diary:
MeController.setToolbarVisibility(this);
ActivityUtils.removeFragmentTOActivity(getSupportFragmentManager(), getSupportFragmentManager().findFragmentById(R.id.content));
ActivityUtils.addFragmentToActivity(getSupportFragmentManager(), new DiariesFragment(), R.id.content);
break;
case R.id.menu_me:
findViewById(R.id.toolbar).setVisibility(View.GONE);
ActivityUtils.removeFragmentTOActivity(getSupportFragmentManager(), getSupportFragmentManager().findFragmentById(R.id.content));
ActivityUtils.addFragmentToActivity(getSupportFragmentManager(), new MeFragment(), R.id.content);
break;
case R.id.menu_new:
bottomNavigationView.setVisibility(View.GONE);
MeController.setToolbarVisibility(this);
ActivityUtils.removeFragmentTOActivity(getSupportFragmentManager(), getSupportFragmentManager().findFragmentById(R.id.content));
ActivityUtils.addFragmentToActivity(getSupportFragmentManager(), new AddDiaryFragment(), R.id.content);
break;
}
return true;
};
}
MainActivity的layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:fitsSystemWindows="true"
android:theme="@style/Widget.AppCompat.Toolbar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/navigation_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/menu_navigation"
android:background="?android:attr/windowBackground"/>
</LinearLayout>
- Switch between different fragments in ViewPager2, and add diary, personal center and diary list to the corresponding navigation bar.
public class DiariesFragment extends Fragment {
private DiariesController mController;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mController = new DiariesController(this);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_diaries, container, false);
mController.setDiariesList(root.findViewById(R.id.diaries_list));
return root;
}
@Override
public void onResume() {
super.onResume();
mController.loadDiaries();
}
}
DiariesFragment的layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/diaries_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
public class AddDiaryFragment extends Fragment implements View.OnClickListener {
private AddDiaryController mController;
private View edit_layout;
private Button btn_confirm;
private EditText edit_title;
private EditText edit_desc;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mController = new AddDiaryController(this);
}
private void initView(View view) {
btn_confirm = view.findViewById(R.id.add_diary_confirm);
btn_confirm.setOnClickListener(this);
edit_title = view.findViewById(R.id.edit_add_title);
edit_desc = view.findViewById(R.id.edit_add_desc);
edit_layout = view.findViewById(R.id.edit_layout);
edit_layout.setOnClickListener(this);
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.menu_cancel, menu);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_cancel:
mController.closeWriteDiary(getActivity().getSupportFragmentManager(), this);
mController.setNavigationVisibility();
return true;
}
return false;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_add_diary, container, false);
initView(root);
return root;
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.add_diary_confirm:
mController.addDiaryToRepository(edit_title.getText().toString().trim(), edit_desc.getText().toString().trim());
mController.setNavigationVisibility();
mController.closeWriteDiary(getActivity().getSupportFragmentManager(), this);
break;
case R.id.edit_layout:
mController.changeFocus(edit_desc);
break;
}
}
}
AddDiaryFragment的layout
<?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:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:orientation="vertical">
<EditText
android:id="@+id/edit_add_title"
android:hint="@string/add_title_hint"
android:minLines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:id="@+id/edit_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginTop="5dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="5dp"
android:paddingTop="5dp"
android:paddingEnd="5dp"
android:paddingBottom="5dp"
android:background="@drawable/edit_background">
<EditText
android:id="@+id/edit_add_desc"
android:hint="@string/add_title_description"
android:gravity="top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:background="@null"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/add_diary_confirm"
android:text="@string/btn_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
- Save the application password encrypted and in the file. Get the password every time you log in and compare it.
public class LoginDirectActivity extends AppCompatActivity implements View.OnClickListener {
private EditText edit_input_text;
private Button btn_comeIn;
private TextView tv_setPsw;
private static final String TAG = "Login2Activity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_direct_login);
bindView();
}
private void bindView() {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
edit_input_text = findViewById(R.id.edit_login2_input_text);
btn_comeIn = findViewById(R.id.btn_login2_comeIn);
btn_comeIn.setOnClickListener(this);
tv_setPsw = findViewById(R.id.tv_setPsw);
tv_setPsw.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.tv_setPsw:
Intent setPsw_intent = new Intent(LoginDirectActivity.this, LoginActivity.class);
startActivity(setPsw_intent);
LoginDirectActivity.this.finish();
// overridePendingTransition(R.anim.out_to_left,R.anim.in_from_right);
break;
case R.id.btn_login2_comeIn:
String psw = edit_input_text.getText().toString().trim();
if (psw.isEmpty()) {
Toast.makeText(this, "密码不能为空!", Toast.LENGTH_SHORT).show();
return;
}
String readInfoByContext = FileUtils.readInfoByContext(this);
if (psw.equals(readInfoByContext)) {
Toast.makeText(this, "登录成功!", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
// overridePendingTransition(R.anim.out_to_left,R.anim.in_from_right);
} else {
Toast.makeText(this, "密码不正确!", Toast.LENGTH_SHORT).show();
}
break;
}
}
}
LoginDirectActivity 的layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.LoginDirectActivity">
<Button
android:id="@+id/btn_login2_comeIn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginEnd="40dp"
android:text="进入"
app:layout_constraintBottom_toTopOf="@+id/guideline5"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginEnd="40dp"
android:gravity="center_vertical"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline7">
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:src="@mipmap/come_in_key" />
<EditText
android:id="@+id/edit_login2_input_text"
android:hint="输入您的密码"
android:inputType="textPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.22" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.58" />
<TextView
android:id="@+id/tv_login2_password_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="输入密码"
android:textSize="30sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline4" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.4" />
<TextView
android:id="@+id/tv_setPsw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="设置密码"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="@+id/linearLayout"
app:layout_constraintTop_toBottomOf="@+id/linearLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
- Use SharedPrefrenced to store diary content and title.
public final class SharedPreferencesUtils {
private static final SimpleArrayMap<String, SharedPreferencesUtils> mCaches = new SimpleArrayMap<>();
private SharedPreferences mSharedPreferences;
private SharedPreferencesUtils(final String spName, final int mode) {
mSharedPreferences = YyApplication.get().getSharedPreferences(spName, mode);
}
public static SharedPreferencesUtils getInstance(String spName) {
SharedPreferencesUtils utils = mCaches.get(spName);
if (utils == null) {
utils = new SharedPreferencesUtils(spName, Context.MODE_PRIVATE);
}
return utils;
}
public void put(final String key, final String value) {
mSharedPreferences.edit().putString(key, value).apply();
}
public String get(final String key) {
return mSharedPreferences.getString(key, "");
}
public void remove(final String key) {
mSharedPreferences.edit().remove(key).apply();
}
}
Summarize
The above is the content of today’s talk. This article only briefly introduces the Android Diary APP. It is necessary to master the above knowledge points and be able to better understand the application logic.