一.数据库的设计及封装(Room)
1.实体类entity的设计
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
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); } } }