• 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);
             }
         }
     }
  • 相关阅读:
    Spring AOP两种实现方式
    重温SQL——行转列,列转行
    SpringMVC-Spring-Hibernate项目搭建之一-- 搭建maven 项目 & servlet的demo
    Linnx 服务器中mysql 无法正常访问问题
    SpringMVC-Spring-Hibernate项目搭建之三-- freemarker & 静态资源整合
    one2many &&many2many
    SQL学习
    使用Maven导出项目依赖的jar包
    Java Hash Collision之数据生产
    HashMap出现Hash DOS攻击的问题
  • 原文地址:https://www.cnblogs.com/best-hym/p/12315926.html
Copyright © 2020-2023  润新知