Android学习进度五--单词记录本小结

经过一段时间对安卓数据库的学习,将所学内容进行一次总结,主要使用了Room,Navigation导航等知识点。

小程序功能有:单词的添加、一键删除所有单词、切换卡片视图或普通视图、搜索单词并实时刷新单词列表、单词右滑或左滑删除

一.数据库的设计及封装(Room)

1.实体类entity的设计

由于是简单的单词记录,所以表的设计并不复杂,只需要知道单词及其汉语意思即可。不过因为功能的需要,添加一个boolean来判断是否需要隐藏单词的汉语意思,以及每个表都需要的id。

 package com.example.words;
 
 import androidx.room.ColumnInfo;
 import androidx.room.Entity;
 import androidx.room.PrimaryKey;
 
 @Entity
 public class Word {
     @PrimaryKey(autoGenerate = true)
      private int id;
      @ColumnInfo(name = "english_word")
      private String word;
      @ColumnInfo(name = "chinese_meaning")
      private String chineseMeaning;
      @ColumnInfo(name = "chinese_invisible")
      private boolean chineseInvisible;
  
      boolean isChineseInvisible() {
          return chineseInvisible;
      }
  
      void setChineseInvisible(boolean chineseInvisible) {
          this.chineseInvisible = chineseInvisible;
      }
  
      public Word(String word, String chineseMeaning) {
          this.word = word;
          this.chineseMeaning = chineseMeaning;
      }
  
      public int getId() {
          return id;
      }
  
      public void setId(int id) {
          this.id = id;
      }
  
      public String getWord() {
          return word;
      }
  
      public void setWord(String word) {
          this.word = word;
      }
  
      String getChineseMeaning() {
          return chineseMeaning;
      }
  }

2.dao

由功能的需要可分析出,dao需要实现对entity的增加、删除、获取所有、根据条件获取相关单词、删除所有。

 package com.example.words;
 
 import androidx.lifecycle.LiveData;
 import androidx.room.Dao;
 import androidx.room.Delete;
 import androidx.room.Insert;
 import androidx.room.Query;
 import androidx.room.Update;
 
 import java.util.List;
 
 @Dao
 public interface WordDao {
     //增加单词
     @Insert
     void insertWords(Word... words);
 
     //更新单词
     @Update
     void updateWords(Word... words);
 
     //删除单词
     @Delete
     void deleteWords(Word... words);
 
     //删除所有单词
     @Query("DElETE FROM WORD")
     void deleteAllWords();
 
     //获取所有单词
     @Query("SELECT * FROM WORD ORDER BY ID DESC ")
     LiveData<List<Word>> getAllWordsLive();
 
     //根据关键词查询单词
     @Query("SELECT * FROM WORD WHERE english_word LIKE :pattern ORDER BY ID DESC")
     LiveData<List<Word>> findWordsWithPattern(String pattern);
 }

3.database

用来获取dao。

 package com.example.roombasic;
  import android.content.Context;
  import androidx.annotation.NonNull;
 import androidx.room.Database;
 import androidx.room.Room;
 import androidx.room.RoomDatabase;
 import androidx.room.migration.Migration;
 import androidx.sqlite.db.SupportSQLiteDatabase;
  @Database(entities = {Word.class},version = 2,exportSchema = false)
 public abstract class WordDatabase extends RoomDatabase {
     private static WordDatabase INSTANCE;
     static synchronized WordDatabase getDatabase(Context context){
         if (INSTANCE == null) {
             INSTANCE = Room.databaseBuilder(context.getApplicationContext(),WordDatabase.class,"word_database")
                     .addMigrations(MIGRATION_1_2)
                     .build();
         }
         return INSTANCE;
     }
      public abstract WordDao getWordDao();
      //之前学习数据库版本迁移所用的迁移方式
     private static final Migration MIGRATION_1_2 = new Migration(1,2) {
         @Override
         public void migrate(@NonNull SupportSQLiteDatabase database) {
             database.execSQL("ALTER TABLE word ADD COLUMN is_ok INTEGER NOT NULL DEFAULT 0");
         }
     };
 }

4.repository

为了使用方便放入了entity的工厂,以供viewmodel使用。

 package com.example.words;
 
 import android.content.Context;
 import android.os.AsyncTask;
 
 import androidx.lifecycle.LiveData;
 
 import java.util.List;
 
 class WordRepository {
     private LiveData<List<Word>> allWordsLive;
     private WordDao wordDao;
 
     WordRepository(Context context) {
         WordDataBase wordDataBase = WordDataBase.getDatabase(context.getApplicationContext());
         wordDao = wordDataBase.getWordDao();
         allWordsLive = wordDao.getAllWordsLive();
     }
 
     //异步添加(不在主线程)
     void insertWords(Word... words) {
         new InsertAsyncTask(wordDao).execute(words);
     }
 
     //异步更新(不在主线程)
     void updateWords(Word... words) {
         new UpdateAsyncTask(wordDao).execute(words);
     }
 
     //异步删除(不在主线程)
     void deleteWords(Word... words) {
         new DeleteAsyncTask(wordDao).execute(words);
     }
 
     //异步删除所有(不在主线程)
     void deleteAllWords() {
         new DeleteAllAsyncTask(wordDao).execute();
    }
 
     //获取所有的单词
     LiveData<List<Word>> getAllWordsLive() {
         return allWordsLive;
     }
 
     //根据条件查询
     LiveData<List<Word>> findWordsWithPattern(String pattern) {
         return wordDao.findWordsWithPattern("%" + pattern + "%");
     }
 
     //添加
     static class InsertAsyncTask extends AsyncTask<Word, Void, Void> {
         private WordDao wordDao;
 
         InsertAsyncTask(WordDao wordDao) {
             this.wordDao = wordDao;
         }
 
         @Override
         protected Void doInBackground(Word... words) {
             wordDao.insertWords(words);
             return null;
         }
     }
 
     //更新
     static class UpdateAsyncTask extends AsyncTask<Word, Void, Void> {
         private WordDao wordDao;
 
         UpdateAsyncTask(WordDao wordDao) {
             this.wordDao = wordDao;
         }
 
         @Override
         protected Void doInBackground(Word... words) {
             wordDao.updateWords(words);
             return null;
         }
     }
 
     //删除
     static class DeleteAsyncTask extends AsyncTask<Word, Void, Void> {
         private WordDao wordDao;
 
         DeleteAsyncTask(WordDao wordDao) {
             this.wordDao = wordDao;
         }
 
         @Override
         protected Void doInBackground(Word... words) {
             wordDao.deleteWords(words);
             return null;
         }
     }
 
     //删除所有
     static class DeleteAllAsyncTask extends AsyncTask<Void, Void, Void> {
         private WordDao wordDao;
 
         DeleteAllAsyncTask(WordDao wordDao) {
             this.wordDao = wordDao;
         }
 
         @Override
        protected Void doInBackground(Void... voids) {
             wordDao.deleteAllWords();
             return null;
         }
     }
 }

二、ViewModel

ViewModel来进行代码中的各种对数据的操作。

 package com.example.words;
 
 import android.app.Application;
 
 import androidx.annotation.NonNull;
 import androidx.lifecycle.AndroidViewModel;
 import androidx.lifecycle.LiveData;
 
 import java.util.List;
 
 public class WordViewModel extends AndroidViewModel {
     private WordRepository wordRepository;
 
     public WordViewModel(@NonNull Application application) {
         super(application);
         wordRepository = new WordRepository(application);
     }
 
     //获取所有单词
     LiveData<List<Word>> getAllWordsLive() {
         return wordRepository.getAllWordsLive();
     }
 
     //根据查询条件获得单词
     LiveData<List<Word>> findWordsWithPattern(String pattern) {
         return wordRepository.findWordsWithPattern(pattern);
     }
 
     //增加
     void insertWords(Word... words) {
         wordRepository.insertWords(words);
     }
 
     //更新
     void updateWords(Word... words) {
         wordRepository.updateWords(words);
     }

    //删除
     void deleteWords(Word... words) {
         wordRepository.deleteWords(words);
     }
 
     //清空
     void deleteAllWords() {
         wordRepository.deleteAllWords();
     }
 }

三.界面的设计

1.单词列表界面

(1)主界面

 <?xml version="1.0" encoding="utf-8"?>
 <androidx.coordinatorlayout.widget.CoordinatorLayout 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:id="@+id/wordsFragmentView"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context=".WordsFragment">
 
     <com.google.android.material.floatingactionbutton.FloatingActionButton
         android:id="@+id/floatingActionButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="bottom|center_horizontal"
         android:layout_margin="16dp"
         android:clickable="true"
         android:focusable="true"
         app:srcCompat="@drawable/ic_add_white_24dp" />
 
     <androidx.recyclerview.widget.RecyclerView
         android:id="@+id/recyclerView"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
 </androidx.coordinatorlayout.widget.CoordinatorLayout>
  • 界面中加入一个recylerView,是可滑动的列表。

  • 加入一个floatingActionButton,用来跳转到单词添加界面。

(2)菜单界面

在res添加menu资源

 <?xml version="1.0" encoding="utf-8"?>
 <menu xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:android="http://schemas.android.com/apk/res/android">
 
     <item
         android:id="@+id/clearData"
         android:title="清空数据" />
     <item
         android:id="@+id/switchViewType"
         android:title="切换视图" />
     <item
         android:id="@+id/app_bar_search"
         android:icon="@drawable/ic_search_black_24dp"
         android:title="Search"
         app:actionViewClass="android.widget.SearchView"
         app:showAsAction="always" />
 </menu>

2.单词添加界面

该界面较为简单。

3.卡片和普通列表视图

(1)卡片视图

  • switch组件的高为占满,宽用padding属性来占满,start 为 30dp,end 为 15dp。

  • 在左侧的容器属性中,onclick设为true,背景设置为selectableItemBackground,点击显波纹状。

  • 层次为结构如图。

(2)普通视图

4.界面之间的navigation

四.主要逻辑代码

1.单词列表逻辑代码

 package com.example.words;
 
 
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.SharedPreferences;
 import android.graphics.Canvas;
 import android.graphics.Color;
  import android.graphics.drawable.ColorDrawable;
  import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.SearchView;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.core.content.ContextCompat;
 import androidx.fragment.app.Fragment;
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.Observer;
 import androidx.lifecycle.ViewModelProviders;
 import androidx.navigation.NavController;
 import androidx.navigation.Navigation;
 import androidx.recyclerview.widget.DefaultItemAnimator;
 import androidx.recyclerview.widget.DividerItemDecoration;
 import androidx.recyclerview.widget.ItemTouchHelper;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.google.android.material.floatingactionbutton.FloatingActionButton;
 import com.google.android.material.snackbar.Snackbar;
 
 import java.util.List;
 
 
 /**
  * A simple {@link Fragment} subclass.
  */
 public class WordsFragment extends Fragment {
     private WordViewModel wordViewModel;
     private RecyclerView recyclerView;
     private MyAdapter myAdapter1, myAdapter2;
     private LiveData<List<Word>> filteredWords;
     private List<Word> allWords;
     private static final String VIEW_TYPE_SHP = "view_type_shp";
     private static final String IS_USING_CARD_VIEW = "is_using_card_view";
     private boolean undoAction;
     private DividerItemDecoration dividerItemDecoration;
 
    public WordsFragment() {
         // Required empty public constructor
 
         setHasOptionsMenu(true);//将菜单栏设置为可见
     }
 
     //此处是菜单部分的逻辑代码,需要采用switch方式来获得用户选择的功能
     @Override
     public boolean onOptionsItemSelected(@NonNull MenuItem item) {
         switch (item.getItemId()) {
             //清空单词功能
             case R.id.clearData:
                 AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
                 builder.setTitle("清空数据");
                 builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
                         wordViewModel.deleteAllWords();
                     }
                 });
                 builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
 
                     }
                 });
                 builder.create();
                 builder.show();
                 break;
             //切换视图功能(卡片视图和普通视图)
             case R.id.switchViewType:
                 SharedPreferences shp = requireActivity().getSharedPreferences(VIEW_TYPE_SHP, Context.MODE_PRIVATE);
                 boolean viewType = shp.getBoolean(IS_USING_CARD_VIEW, false);
                 SharedPreferences.Editor editor = shp.edit();
                 if (viewType) {
                     recyclerView.setAdapter(myAdapter1);
                     recyclerView.addItemDecoration(dividerItemDecoration);
                     editor.putBoolean(IS_USING_CARD_VIEW, false);
                 } else {
                     recyclerView.setAdapter(myAdapter2);
                     recyclerView.removeItemDecoration(dividerItemDecoration);
                     editor.putBoolean(IS_USING_CARD_VIEW, true);
                 }
                 editor.apply();
         }
         return super.onOptionsItemSelected(item);
     }
 
     //搜索单词菜单
     @Override
     public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
         super.onCreateOptionsMenu(menu, inflater);
         inflater.inflate(R.menu.main_menu, menu);
         //获取搜索item
         SearchView searchView = (SearchView) menu.findItem(R.id.app_bar_search).getActionView();
         searchView.setMaxWidth(1000);
         //设置监听
         searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
             @Override
             public boolean onQueryTextSubmit(String query) {
                 return false;
             }
 
             @Override
             public boolean onQueryTextChange(String newText) {
                //获得用户输入的内容
                 String pattern = newText.trim();
                 //将之前主页面的监听删除
                 filteredWords.removeObservers(getViewLifecycleOwner());
                 filteredWords = wordViewModel.findWordsWithPattern(pattern);
                 //搜索的单词的监听
                 filteredWords.observe(getViewLifecycleOwner(), new Observer<List<Word>>() {
                     @Override
                     public void onChanged(List<Word> words) {
                         int temp = myAdapter1.getItemCount();
                         allWords = words;
                         //刷新列表
                         if (temp != words.size()) {
                             myAdapter1.submitList(words);
                             myAdapter2.submitList(words);
                         }
                     }
                 });
                 return true;
             }
         });
     }
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                              Bundle savedInstanceState) {
         // Inflate the layout for this fragment
         return inflater.inflate(R.layout.fragment_words, container, false);
     }
 
     //主要的逻辑代码都写在此处
     @Override
     public void onActivityCreated(@Nullable Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         wordViewModel = ViewModelProviders.of(requireActivity()).get(WordViewModel.class);
         recyclerView = requireActivity().findViewById(R.id.recyclerView);
         recyclerView.setLayoutManager(new LinearLayoutManager(requireActivity()));
         myAdapter1 = new MyAdapter(false, wordViewModel);
         myAdapter2 = new MyAdapter(true, wordViewModel);
         recyclerView.setItemAnimator(new DefaultItemAnimator() {
             @Override
             public void onAnimationFinished(@NonNull RecyclerView.ViewHolder viewHolder) {
                 super.onAnimationFinished(viewHolder);
                 LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
                 if (linearLayoutManager != null) {
                     int firstPosition = linearLayoutManager.findFirstVisibleItemPosition();
                     int lastPosition = linearLayoutManager.findLastVisibleItemPosition();
                     for (int i = firstPosition; i <= lastPosition; i++) {
                         MyAdapter.MyViewHolder holder = (MyAdapter.MyViewHolder) recyclerView.findViewHolderForLayoutPosition(i);
                         if (holder != null) {
                             holder.textViewNumber.setText(String.valueOf(i + 1));
                         }
                     }
                 }
             }
         });
         //界面列表的视图的偏好选择
         SharedPreferences shp = requireActivity().getSharedPreferences(VIEW_TYPE_SHP, Context.MODE_PRIVATE);
         boolean viewType = shp.getBoolean(IS_USING_CARD_VIEW, false);
         dividerItemDecoration = new DividerItemDecoration(requireActivity(), DividerItemDecoration.VERTICAL);
         if (viewType) {
             recyclerView.setAdapter(myAdapter2);
         } else {
             recyclerView.setAdapter(myAdapter1);
             recyclerView.addItemDecoration(dividerItemDecoration);
         }
         //单词列表的监听,当增加后刷新列表
         filteredWords = wordViewModel.getAllWordsLive();
         filteredWords.observe(getViewLifecycleOwner(), new Observer<List<Word>>() {
             @Override
             public void onChanged(List<Word> words) {
                 int temp = myAdapter1.getItemCount();
                 allWords = words;
                 if (temp != words.size()) {
                     if (temp < words.size() && !undoAction) {
                         recyclerView.smoothScrollBy(0, -200);
                     }
                     undoAction = false;
                     myAdapter1.submitList(words);
                     myAdapter2.submitList(words);
                 }
             }
         });

         //左右滑动删除功能
         new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.START | ItemTouchHelper.END) {
             @Override
             public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
 //                Word wordFrom = allWords.get(viewHolder.getAdapterPosition());
 //                Word wordTo = allWords.get(target.getAdapterPosition());
 //                int idTemp = wordFrom.getId();
 //                wordFrom.setId(wordTo.getId());
 //                wordTo.setId(idTemp);
 //                wordViewModel.updateWords(wordFrom,wordTo);
 //                myAdapter1.notifyItemMoved(viewHolder.getAdapterPosition(),target.getAdapterPosition());
 //                myAdapter2.notifyItemMoved(viewHolder.getAdapterPosition(),target.getAdapterPosition());
                 return false;
             }
 
             @Override
             public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
                 final Word wordToDelete = allWords.get(viewHolder.getAdapterPosition());
                 wordViewModel.deleteWords(wordToDelete);
                 Snackbar.make(requireActivity().findViewById(R.id.wordsFragmentView), "删除此词汇", Snackbar.LENGTH_SHORT)
                         .setAction("撤销", new View.OnClickListener() {
                             @Override
                             public void onClick(View v) {
                                 undoAction = true;
                                 wordViewModel.insertWords(wordToDelete);
                             }
                         }).show();
             }
 
             Drawable icon = ContextCompat.getDrawable(requireActivity(), R.drawable.ic_delete_forever_black_24dp);
             Drawable background = new ColorDrawable(Color.LTGRAY);
 
             @Override
             public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
                 super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
                 View itemView = viewHolder.itemView;
                 int iconMargin = (itemView.getHeight() - icon.getIntrinsicHeight()) / 2;
 
                 int iconLeft, iconRight, iconTop, iconBottom;
                 int backLeft, backRight, backTop, backBottom;
                 backTop = itemView.getTop();
                 backBottom = itemView.getBottom();
                 iconTop = itemView.getTop() + (itemView.getHeight() - icon.getIntrinsicHeight()) / 2;
                 iconBottom = iconTop + icon.getIntrinsicHeight();
                 if (dX > 0) {
                     backLeft = itemView.getLeft();
                     backRight = itemView.getLeft() + (int) dX;
                     background.setBounds(backLeft, backTop, backRight, backBottom);
                     iconLeft = itemView.getLeft() + iconMargin;
                     iconRight = iconLeft + icon.getIntrinsicWidth();
                     icon.setBounds(iconLeft, iconTop, iconRight, iconBottom);
                 } else if (dX < 0) {
                     backRight = itemView.getRight();
                     backLeft = itemView.getRight() + (int) dX;
                     background.setBounds(backLeft, backTop, backRight, backBottom);
                     iconRight = itemView.getRight() - iconMargin;
                     iconLeft = iconRight - icon.getIntrinsicWidth();
                     icon.setBounds(iconLeft, iconTop, iconRight, iconBottom);
                 } else {
                     background.setBounds(0, 0, 0, 0);
                     icon.setBounds(0, 0, 0, 0);
                 }
                 background.draw(c);
                 icon.draw(c);
             }
         }).attachToRecyclerView(recyclerView);
 
         //下方的悬浮按钮,跳转到单词添加页面
         FloatingActionButton floatingActionButton = requireActivity().findViewById(R.id.floatingActionButton);
         floatingActionButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 NavController navController = Navigation.findNavController(v);
                 navController.navigate(R.id.action_wordsFragment_to_addFragment);
             }
         });
     }
 }

2.单词添加页面逻辑代码

package com.example.words;
 
 
import android.content.Context;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
 import android.view.ViewGroup;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Button;
 import android.widget.EditText;
 
 import androidx.annotation.Nullable;
 import androidx.fragment.app.Fragment;
 import androidx.lifecycle.ViewModelProviders;
 import androidx.navigation.NavController;
 import androidx.navigation.Navigation;
 
 
 /**
  * A simple {@link Fragment} subclass.
  */
 public class AddFragment extends Fragment {
     private Button buttonSubmit;
     private EditText editTextEnglish, editTextChinese;
     private WordViewModel wordViewModel;
 
     public AddFragment() {
         // Required empty public constructor
     }
 
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                              Bundle savedInstanceState) {
         // Inflate the layout for this fragment
         return inflater.inflate(R.layout.fragment_add, container, false);
     }
 
     @Override
     public void onActivityCreated(@Nullable Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         wordViewModel = ViewModelProviders.of(requireActivity()).get(WordViewModel.class);
         buttonSubmit = requireActivity().findViewById(R.id.buttonSubmit);
         editTextChinese = requireActivity().findViewById(R.id.editTextChinese);
         editTextEnglish = requireActivity().findViewById(R.id.editTextEnglish);
         //将按钮设为不可点击
         buttonSubmit.setEnabled(false);
         //聚焦到英文输入框
         editTextEnglish.requestFocus();
         //设置调用出用户的键盘并聚焦到英文输入框
         InputMethodManager imm = (InputMethodManager) requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
         if (imm != null) {
             imm.showSoftInput(editTextEnglish, 0);
         }
 
         //设置两个文字输入框的监听,当两个输入框的内容都存在时才可以点击添加按钮
         TextWatcher textWatcher = new TextWatcher() {
             @Override
             public void beforeTextChanged(CharSequence s, int start, int count, int after) {
 
             }
 
             @Override
             public void onTextChanged(CharSequence s, int start, int before, int count) {
                 String english = editTextEnglish.getText().toString().trim();
                 String chinese = editTextChinese.getText().toString().trim();
                 buttonSubmit.setEnabled(!english.isEmpty() && !chinese.isEmpty());
             }
 
             @Override
             public void afterTextChanged(Editable s) {
 
             }
         };
         //加入监听
         editTextEnglish.addTextChangedListener(textWatcher);
         editTextChinese.addTextChangedListener(textWatcher);
         buttonSubmit.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 String english = editTextEnglish.getText().toString().trim();
                 String chinese = editTextChinese.getText().toString().trim();
                 Word word = new Word(english,chinese);
                 wordViewModel.insertWords(word);
                 //添加完毕后跳转到单词列表页面
                 NavController navController = Navigation.findNavController(v);
                 navController.navigateUp();
                 //将键盘收起
                 InputMethodManager imm = (InputMethodManager) requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
                 if (imm != null) {
                     imm.hideSoftInputFromWindow(v.getWindowToken(),0);
                 }
             }
         });
     }
 }

3.主进程页面逻辑代码

 package com.example.words;
 
 import android.content.Context;
 import android.os.Bundle;
 import android.view.inputmethod.InputMethodManager;
 
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.navigation.NavController;
 import androidx.navigation.Navigation;
 import androidx.navigation.ui.NavigationUI;
 
 public class MainActivity extends AppCompatActivity {
     private NavController navController;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         //界面的返回按钮的添加
         navController = Navigation.findNavController(findViewById(R.id.fragment));
         NavigationUI.setupActionBarWithNavController(this, navController);
     }
 
     //点击界面返回按钮后的动作,应该是先收起用户的键盘然后再跳转到主界面。
     @Override
     public boolean onSupportNavigateUp() {
         InputMethodManager imm = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
         if (imm != null) {
             imm.hideSoftInputFromWindow(findViewById(R.id.fragment).getWindowToken(),0);
         }
         navController.navigateUp();
         return super.onSupportNavigateUp();
     }
 }

4.适配器

 package com.example.words;
 
 import android.content.Intent;
 import android.net.Uri;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.CompoundButton;
 import android.widget.Switch;
 import android.widget.TextView;
 
 import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.DiffUtil;
 import androidx.recyclerview.widget.ListAdapter;
 import androidx.recyclerview.widget.RecyclerView;
 
 //构造函数
 public class MyAdapter extends ListAdapter<Word, MyAdapter.MyViewHolder> {
     private boolean useCardView;
     private WordViewModel wordViewModel;
 
     MyAdapter(boolean useCardView, WordViewModel wordViewModel) {
         super(new DiffUtil.ItemCallback<Word>() {
             //判断列表是否刷新的条件--id是否一致
             @Override
             public boolean areItemsTheSame(@NonNull Word oldItem, @NonNull Word newItem) {
                 return oldItem.getId() == newItem.getId();
             }
 
             //判断列表是否刷新的条件--内容是否一致
             @Override
             public boolean areContentsTheSame(@NonNull Word oldItem, @NonNull Word newItem) {
                 return (oldItem.getWord().equals(newItem.getWord())
                         && oldItem.getChineseMeaning().equals(newItem.getChineseMeaning())
                         && oldItem.isChineseInvisible() == newItem.isChineseInvisible());
             }
         });
         this.useCardView = useCardView;
         this.wordViewModel = wordViewModel;
     }
 
     //初始化适配器
     @NonNull
     @Override
     public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
         LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
         View itemView;
         if (useCardView) {
             itemView = layoutInflater.inflate(R.layout.cell_card_2, parent, false);
         } else {
             itemView = layoutInflater.inflate(R.layout.cell_normal_2, parent, false);
         }
         //点击单词后跳转到查询网页
         final MyViewHolder holder = new MyViewHolder(itemView);
         holder.itemView.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 Uri uri = Uri.parse("http://m.youdao.com/dict?le=eng&q=" + holder.textViewEnglish.getText());
                 Intent intent = new Intent(Intent.ACTION_VIEW);
                 intent.setData(uri);
                 holder.itemView.getContext().startActivity(intent);
             }
         });
         //监听列表的switch点击
         holder.aSwitchChineseInvisible.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
             @Override
             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                 Word word = (Word) holder.itemView.getTag(R.id.word_for_view_holder);
                 if (isChecked) {
                     holder.textViewChinese.setVisibility(View.GONE);
                     word.setChineseInvisible(true);
                     wordViewModel.updateWords(word);
                 } else {
                     holder.textViewChinese.setVisibility(View.VISIBLE);
                     word.setChineseInvisible(false);
                     wordViewModel.updateWords(word);
                 }
             }
         });
         return new MyViewHolder(itemView);
     }
 
     //将数据与recyclerview进行绑定
     @Override
     public void onBindViewHolder(@NonNull final MyViewHolder holder, int position) {
         final Word word = getItem(position);
         holder.itemView.setTag(R.id.word_for_view_holder, word);
         holder.textViewNumber.setText(String.valueOf(position + 1));
         holder.textViewEnglish.setText(word.getWord());
         holder.textViewChinese.setText(word.getChineseMeaning());
         if (word.isChineseInvisible()) {
             holder.textViewChinese.setVisibility(View.GONE);
             holder.aSwitchChineseInvisible.setChecked(true);
         } else {
             holder.textViewChinese.setVisibility(View.VISIBLE);
             holder.aSwitchChineseInvisible.setChecked(false);
         }
     }
 
     //刷新视图后重新编号
     @Override
     public void onViewAttachedToWindow(@NonNull MyViewHolder holder) {
         super.onViewAttachedToWindow(holder);
         holder.textViewNumber.setText(String.valueOf(holder.getAdapterPosition() + 1));
     }
 
     static class MyViewHolder extends RecyclerView.ViewHolder {
         TextView textViewNumber, textViewEnglish, textViewChinese;
         Switch aSwitchChineseInvisible;
 
         //控件的获取
         MyViewHolder(@NonNull View itemView) {
             super(itemView);
             textViewNumber = itemView.findViewById(R.id.textViewNumber);
             textViewEnglish = itemView.findViewById(R.id.textViewEnglish);
             textViewChinese = itemView.findViewById(R.id.textViewChinese);
             aSwitchChineseInvisible = itemView.findViewById(R.id.switchChineseInvisible);
         }
     }
 }
原文地址:https://www.cnblogs.com/best-hym/p/12315926.html