|
|
|
@ -52,49 +52,94 @@ import static com.example.musicplayer.app.Constant.SINGER_NAME_KEY;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Created by 残渊 on 2018/11/25.
|
|
|
|
* Created by 残渊 on 2018/11/25.
|
|
|
|
|
|
|
|
* 这个类表示专辑内容的Fragment,用于展示专辑相关的详细信息,如专辑封面、歌手、发行时间等,
|
|
|
|
|
|
|
|
* 并且包含了专辑内歌曲列表、专辑信息等不同页面的切换展示以及专辑收藏相关功能。
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
public class AlbumContentFragment extends Fragment {
|
|
|
|
public class AlbumContentFragment extends Fragment {
|
|
|
|
private static final String TAG = "AlbumContentFragment";
|
|
|
|
private static final String TAG = "AlbumContentFragment";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 专辑名称
|
|
|
|
|
|
|
|
private String mAlbumName,
|
|
|
|
private String mAlbumName, mSingerName, mAlbumPic, mPublicTime, mId;
|
|
|
|
// 歌手名称
|
|
|
|
|
|
|
|
mSingerName,
|
|
|
|
|
|
|
|
// 专辑封面图片的路径或资源标识等
|
|
|
|
|
|
|
|
mAlbumPic,
|
|
|
|
|
|
|
|
// 专辑发行时间
|
|
|
|
|
|
|
|
mPublicTime,
|
|
|
|
|
|
|
|
// 专辑的唯一标识(例如ID)
|
|
|
|
|
|
|
|
mId;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 用于实现页面滑动切换效果的ViewPager,来自MaterialViewPager库
|
|
|
|
private MaterialViewPager mViewPager;
|
|
|
|
private MaterialViewPager mViewPager;
|
|
|
|
|
|
|
|
// 顶部的Toolbar,用于显示标题、操作按钮等
|
|
|
|
private Toolbar toolbar;
|
|
|
|
private Toolbar toolbar;
|
|
|
|
|
|
|
|
// 专辑背景布局,用于设置专辑封面等作为背景展示效果
|
|
|
|
private RelativeLayout mAlbumBackground;
|
|
|
|
private RelativeLayout mAlbumBackground;
|
|
|
|
|
|
|
|
// 用于显示歌手名称的TextView
|
|
|
|
private TextView mSingerNameTv;
|
|
|
|
private TextView mSingerNameTv;
|
|
|
|
|
|
|
|
// 用于显示发行时间的TextView
|
|
|
|
private TextView mPublicTimeTv;
|
|
|
|
private TextView mPublicTimeTv;
|
|
|
|
|
|
|
|
// 用于显示专辑封面图片的ImageView
|
|
|
|
private ImageView mAlbumPicIv;
|
|
|
|
private ImageView mAlbumPicIv;
|
|
|
|
|
|
|
|
// 表示收藏按钮的菜单项
|
|
|
|
private MenuItem mLoveBtn;
|
|
|
|
private MenuItem mLoveBtn;
|
|
|
|
|
|
|
|
// 用于记录专辑是否已被收藏的状态
|
|
|
|
private boolean mLove;
|
|
|
|
private boolean mLove;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Fragment创建时调用,设置该Fragment有菜单选项(用于显示右上角的收藏按钮菜单)
|
|
|
|
|
|
|
|
* @param savedInstanceState 保存的实例状态信息(如果有的话)
|
|
|
|
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
|
|
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
setHasOptionsMenu(true);//加上这句话,menu才会显示出来
|
|
|
|
setHasOptionsMenu(true);//加上这句话,menu才会显示出来
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 创建Fragment的视图,加载对应的布局文件,并获取布局中的相关视图组件
|
|
|
|
|
|
|
|
* @param inflater 用于将布局文件实例化为视图对象的布局填充器
|
|
|
|
|
|
|
|
* @param container 父视图容器
|
|
|
|
|
|
|
|
* @param savedInstanceState 保存的实例状态信息(如果有的话)
|
|
|
|
|
|
|
|
* @return 返回创建好的视图对象
|
|
|
|
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
|
|
Bundle savedInstanceState) {
|
|
|
|
Bundle savedInstanceState) {
|
|
|
|
getBundle();
|
|
|
|
getBundle();
|
|
|
|
|
|
|
|
// 加载fragment_album_content布局文件并创建视图对象
|
|
|
|
View view = inflater.inflate(R.layout.fragment_album_content, container, false);
|
|
|
|
View view = inflater.inflate(R.layout.fragment_album_content, container, false);
|
|
|
|
|
|
|
|
// 从布局中找到对应的MaterialViewPager组件
|
|
|
|
mViewPager = view.findViewById(R.id.materialViewPager);
|
|
|
|
mViewPager = view.findViewById(R.id.materialViewPager);
|
|
|
|
|
|
|
|
// 获取MaterialViewPager中的Toolbar组件
|
|
|
|
toolbar = mViewPager.getToolbar();
|
|
|
|
toolbar = mViewPager.getToolbar();
|
|
|
|
|
|
|
|
// 从MaterialViewPager的头部背景容器中找到对应的RelativeLayout组件,用于设置专辑背景
|
|
|
|
mAlbumBackground = mViewPager.getHeaderBackgroundContainer().findViewById(R.id.relative_album);
|
|
|
|
mAlbumBackground = mViewPager.getHeaderBackgroundContainer().findViewById(R.id.relative_album);
|
|
|
|
|
|
|
|
// 从MaterialViewPager的头部背景容器中找到对应的ImageView组件,用于显示专辑封面图片
|
|
|
|
mAlbumPicIv = mViewPager.getHeaderBackgroundContainer().findViewById(R.id.iv_album);
|
|
|
|
mAlbumPicIv = mViewPager.getHeaderBackgroundContainer().findViewById(R.id.iv_album);
|
|
|
|
|
|
|
|
// 从MaterialViewPager的头部背景容器中找到对应的TextView组件,用于显示歌手名称
|
|
|
|
mSingerNameTv = mViewPager.getHeaderBackgroundContainer().findViewById(R.id.tv_singer_name);
|
|
|
|
mSingerNameTv = mViewPager.getHeaderBackgroundContainer().findViewById(R.id.tv_singer_name);
|
|
|
|
|
|
|
|
// 从MaterialViewPager的头部背景容器中找到对应的TextView组件,用于显示发行时间
|
|
|
|
mPublicTimeTv = mViewPager.getHeaderBackgroundContainer().findViewById(R.id.tv_public_time);
|
|
|
|
mPublicTimeTv = mViewPager.getHeaderBackgroundContainer().findViewById(R.id.tv_public_time);
|
|
|
|
return view;
|
|
|
|
return view;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 当Fragment所在的Activity创建完成后调用,用于进一步初始化视图组件和相关设置
|
|
|
|
|
|
|
|
* @param savedInstanceState 保存的实例状态信息(如果有的话)
|
|
|
|
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void onActivityCreated(Bundle savedInstanceState) {
|
|
|
|
public void onActivityCreated(Bundle savedInstanceState) {
|
|
|
|
super.onActivityCreated(savedInstanceState);
|
|
|
|
super.onActivityCreated(savedInstanceState);
|
|
|
|
initView();
|
|
|
|
initView();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 用于创建菜单选项,这里主要是 inflate(加载)收藏按钮对应的菜单布局文件,并获取到收藏按钮菜单项,
|
|
|
|
|
|
|
|
* 同时根据收藏状态显示对应的图标
|
|
|
|
|
|
|
|
* @param menu 菜单对象,用于添加菜单项等操作
|
|
|
|
|
|
|
|
* @param inflater 菜单填充器,用于加载菜单布局文件
|
|
|
|
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
|
|
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
|
|
|
inflater.inflate(R.menu.love, menu);
|
|
|
|
inflater.inflate(R.menu.love, menu);
|
|
|
|
@ -103,43 +148,69 @@ public class AlbumContentFragment extends Fragment {
|
|
|
|
super.onCreateOptionsMenu(menu, inflater);
|
|
|
|
super.onCreateOptionsMenu(menu, inflater);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 初始化视图组件的相关设置,包括设置标题、加载专辑封面图片、设置文本内容、配置Toolbar显示样式以及
|
|
|
|
|
|
|
|
* 为ViewPager设置页面切换的适配器等操作
|
|
|
|
|
|
|
|
*/
|
|
|
|
@SuppressLint("SetTextI18n")
|
|
|
|
@SuppressLint("SetTextI18n")
|
|
|
|
private void initView() {
|
|
|
|
private void initView() {
|
|
|
|
|
|
|
|
// 设置Toolbar的标题为专辑名称
|
|
|
|
toolbar.setTitle(mAlbumName);
|
|
|
|
toolbar.setTitle(mAlbumName);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建一个SimpleTarget对象,用于接收Glide加载图片后的结果,在图片加载完成后进行相关处理
|
|
|
|
SimpleTarget target = new SimpleTarget<Drawable>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
|
|
|
|
SimpleTarget target = new SimpleTarget<Drawable>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void onResourceReady(@Nullable Drawable resource, Transition<? super Drawable> transition) {
|
|
|
|
public void onResourceReady(@Nullable Drawable resource, Transition<? super Drawable> transition) {
|
|
|
|
|
|
|
|
// 将加载后的Drawable资源转换为Bitmap,以便后续设置背景等操作
|
|
|
|
Bitmap bitmap = ((BitmapDrawable) resource).getBitmap();
|
|
|
|
Bitmap bitmap = ((BitmapDrawable) resource).getBitmap();
|
|
|
|
|
|
|
|
// 使用工具方法将Bitmap转换为可设置为背景的Drawable,并设置为专辑背景
|
|
|
|
mAlbumBackground.setBackground(CommonUtil.getForegroundDrawable(bitmap));
|
|
|
|
mAlbumBackground.setBackground(CommonUtil.getForegroundDrawable(bitmap));
|
|
|
|
|
|
|
|
// 将Bitmap设置为ImageView的显示图片,用于显示专辑封面
|
|
|
|
mAlbumPicIv.setImageBitmap(bitmap);
|
|
|
|
mAlbumPicIv.setImageBitmap(bitmap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// 使用Glide库加载专辑封面图片,设置占位图、加载出错时的图片,并将加载结果传递给SimpleTarget对象处理
|
|
|
|
Glide.with(getActivity())
|
|
|
|
Glide.with(getActivity())
|
|
|
|
.load(mAlbumPic)
|
|
|
|
.load(mAlbumPic)
|
|
|
|
.apply(RequestOptions.placeholderOf(R.drawable.welcome))
|
|
|
|
.apply(RequestOptions.placeholderOf(R.drawable.welcome))
|
|
|
|
.apply(RequestOptions.errorOf(R.drawable.welcome))
|
|
|
|
.apply(RequestOptions.errorOf(R.drawable.welcome))
|
|
|
|
.into(target);
|
|
|
|
.into(target);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置歌手名称的TextView显示内容,添加前缀 "歌手 "
|
|
|
|
mSingerNameTv.setText("歌手 " + mSingerName);
|
|
|
|
mSingerNameTv.setText("歌手 " + mSingerName);
|
|
|
|
|
|
|
|
// 设置发行时间的TextView显示内容,添加前缀 "发行时间 "
|
|
|
|
mPublicTimeTv.setText("发行时间 " + mPublicTime);
|
|
|
|
mPublicTimeTv.setText("发行时间 " + mPublicTime);
|
|
|
|
|
|
|
|
// 设置Toolbar标题文字颜色为白色
|
|
|
|
toolbar.setTitleTextColor(getActivity().getResources().getColor(R.color.white));
|
|
|
|
toolbar.setTitleTextColor(getActivity().getResources().getColor(R.color.white));
|
|
|
|
if (toolbar != null) {
|
|
|
|
if (toolbar!= null) {
|
|
|
|
|
|
|
|
// 将Toolbar设置为Activity的支持ActionBar(用于显示标题、导航按钮等功能)
|
|
|
|
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
|
|
|
|
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
|
|
|
|
|
|
|
|
|
|
|
|
final ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
|
|
|
final ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
|
|
|
if (actionBar != null) {
|
|
|
|
if (actionBar!= null) {
|
|
|
|
|
|
|
|
// 设置ActionBar显示返回按钮(用于导航返回上一个页面)
|
|
|
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
|
|
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
|
|
|
|
|
|
|
// 设置ActionBar显示返回按钮(确保图标显示等)
|
|
|
|
actionBar.setDisplayShowHomeEnabled(true);
|
|
|
|
actionBar.setDisplayShowHomeEnabled(true);
|
|
|
|
|
|
|
|
// 设置ActionBar显示标题(已设置过标题内容)
|
|
|
|
actionBar.setDisplayShowTitleEnabled(true);
|
|
|
|
actionBar.setDisplayShowTitleEnabled(true);
|
|
|
|
|
|
|
|
// 不使用logo作为显示元素(这里可能是按照需求禁用)
|
|
|
|
actionBar.setDisplayUseLogoEnabled(false);
|
|
|
|
actionBar.setDisplayUseLogoEnabled(false);
|
|
|
|
|
|
|
|
// 设置Home按钮可用(点击返回按钮等操作生效)
|
|
|
|
actionBar.setHomeButtonEnabled(true);
|
|
|
|
actionBar.setHomeButtonEnabled(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//返回键的监听
|
|
|
|
// 为Toolbar的返回按钮设置点击监听事件,点击时弹出Fragment栈,返回上一个Fragment页面
|
|
|
|
toolbar.setNavigationOnClickListener(v -> getActivity().getSupportFragmentManager().popBackStack());
|
|
|
|
toolbar.setNavigationOnClickListener(v -> getActivity().getSupportFragmentManager().popBackStack());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 为MaterialViewPager的ViewPager设置页面切换的适配器,用于展示不同的Fragment页面(如歌曲列表、专辑信息页面)
|
|
|
|
mViewPager.getViewPager().setAdapter(new FragmentStatePagerAdapter(getActivity().getSupportFragmentManager()) {
|
|
|
|
mViewPager.getViewPager().setAdapter(new FragmentStatePagerAdapter(getActivity().getSupportFragmentManager()) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 根据传入的位置参数,返回对应的Fragment实例,用于在ViewPager中显示不同页面
|
|
|
|
|
|
|
|
* @param position 页面位置索引,0表示歌曲列表页面,1表示专辑信息页面
|
|
|
|
|
|
|
|
* @return 返回对应的Fragment实例
|
|
|
|
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Fragment getItem(int position) {
|
|
|
|
public Fragment getItem(int position) {
|
|
|
|
switch (position) {
|
|
|
|
switch (position) {
|
|
|
|
@ -152,11 +223,20 @@ public class AlbumContentFragment extends Fragment {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 返回ViewPager中页面的总数,这里固定为2个页面(歌曲列表和专辑信息页面)
|
|
|
|
|
|
|
|
* @return 页面总数
|
|
|
|
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public int getCount() {
|
|
|
|
public int getCount() {
|
|
|
|
return 2;
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 根据页面位置索引,返回对应的页面标题,用于在ViewPager的标题栏显示
|
|
|
|
|
|
|
|
* @param position 页面位置索引,0表示歌曲列表页面,1表示专辑信息页面
|
|
|
|
|
|
|
|
* @return 对应的页面标题字符串
|
|
|
|
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public CharSequence getPageTitle(int position) {
|
|
|
|
public CharSequence getPageTitle(int position) {
|
|
|
|
switch (position) {
|
|
|
|
switch (position) {
|
|
|
|
@ -169,43 +249,60 @@ public class AlbumContentFragment extends Fragment {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 将ViewPager与标题栏关联起来,使标题栏能根据ViewPager的页面切换显示对应的标题和指示器效果
|
|
|
|
mViewPager.getPagerTitleStrip().setViewPager(mViewPager.getViewPager());
|
|
|
|
mViewPager.getPagerTitleStrip().setViewPager(mViewPager.getViewPager());
|
|
|
|
|
|
|
|
// 设置标题栏指示器的颜色(例如切换页面时的滑动条颜色)
|
|
|
|
mViewPager.getPagerTitleStrip().setIndicatorColorResource(R.color.yellow);
|
|
|
|
mViewPager.getPagerTitleStrip().setIndicatorColorResource(R.color.yellow);
|
|
|
|
|
|
|
|
// 设置标题栏每个标题标签的背景颜色
|
|
|
|
mViewPager.getPagerTitleStrip().setTabBackground(R.color.tab);
|
|
|
|
mViewPager.getPagerTitleStrip().setTabBackground(R.color.tab);
|
|
|
|
|
|
|
|
// 设置标题栏文字的颜色状态列表(例如不同状态下的文字颜色,按下、正常等状态)
|
|
|
|
mViewPager.getPagerTitleStrip().setTextColorStateListResource(R.color.white);
|
|
|
|
mViewPager.getPagerTitleStrip().setTextColorStateListResource(R.color.white);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 处理菜单选项的点击事件,这里主要是处理收藏按钮的点击逻辑,根据专辑当前收藏状态进行相应操作,
|
|
|
|
|
|
|
|
* 如收藏或取消收藏专辑,并更新界面显示、数据库记录以及发送收藏状态改变的事件
|
|
|
|
|
|
|
|
* @param item 被点击的菜单项
|
|
|
|
|
|
|
|
* @return 返回是否处理了该点击事件,如果返回true,表示已处理,不再继续向上传递事件
|
|
|
|
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
case R.id.btn_love:
|
|
|
|
case R.id.btn_love:
|
|
|
|
if (mLove) {
|
|
|
|
if (mLove) {
|
|
|
|
|
|
|
|
// 如果专辑已收藏,执行取消收藏操作,从数据库中删除对应的收藏记录
|
|
|
|
LitePal.deleteAllAsync(AlbumCollection.class, "albumId=?", mId).listen(new UpdateOrDeleteCallback() {
|
|
|
|
LitePal.deleteAllAsync(AlbumCollection.class, "albumId=?", mId).listen(new UpdateOrDeleteCallback() {
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void onFinish(int rowsAffected) {
|
|
|
|
public void onFinish(int rowsAffected) {
|
|
|
|
|
|
|
|
// 更新收藏按钮图标为未收藏状态图标
|
|
|
|
mLoveBtn.setIcon(R.drawable.favorites);
|
|
|
|
mLoveBtn.setIcon(R.drawable.favorites);
|
|
|
|
|
|
|
|
// 显示提示Toast消息,告知用户已取消收藏
|
|
|
|
CommonUtil.showToast(getActivity(), "你已取消收藏该专辑");
|
|
|
|
CommonUtil.showToast(getActivity(), "你已取消收藏该专辑");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// 如果专辑未收藏,创建一个AlbumCollection对象,设置专辑相关信息,准备保存到数据库作为收藏记录
|
|
|
|
AlbumCollection albumCollection = new AlbumCollection();
|
|
|
|
AlbumCollection albumCollection = new AlbumCollection();
|
|
|
|
albumCollection.setAlbumId(mId);
|
|
|
|
albumCollection.setAlbumId(mId);
|
|
|
|
albumCollection.setAlbumName(mAlbumName);
|
|
|
|
albumCollection.setAlbumName(mAlbumName);
|
|
|
|
albumCollection.setAlbumPic(mAlbumPic);
|
|
|
|
albumCollection.setAlbumPic(mAlbumPic);
|
|
|
|
albumCollection.setPublicTime(mPublicTime);
|
|
|
|
albumCollection.setPublicTime(mPublicTime);
|
|
|
|
albumCollection.setSingerName(mSingerName);
|
|
|
|
albumCollection.setSingerName(mSingerName);
|
|
|
|
|
|
|
|
// 异步保存收藏记录到数据库
|
|
|
|
albumCollection.saveAsync().listen(new SaveCallback() {
|
|
|
|
albumCollection.saveAsync().listen(new SaveCallback() {
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void onFinish(boolean success) {
|
|
|
|
public void onFinish(boolean success) {
|
|
|
|
|
|
|
|
// 更新收藏按钮图标为已收藏状态图标
|
|
|
|
mLoveBtn.setIcon(R.drawable.favorites_selected);
|
|
|
|
mLoveBtn.setIcon(R.drawable.favorites_selected);
|
|
|
|
|
|
|
|
// 显示提示Toast消息,告知用户收藏专辑成功
|
|
|
|
CommonUtil.showToast(getActivity(), "收藏专辑成功");
|
|
|
|
CommonUtil.showToast(getActivity(), "收藏专辑成功");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mLove = !mLove;
|
|
|
|
mLove =!mLove;
|
|
|
|
//发送收藏改变的事件
|
|
|
|
// 发送专辑收藏状态改变的事件,通过EventBus通知其他可能关注该事件的地方进行相应处理
|
|
|
|
EventBus.getDefault().post(new AlbumCollectionEvent());
|
|
|
|
EventBus.getDefault().post(new AlbumCollectionEvent());
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -213,8 +310,11 @@ public class AlbumContentFragment extends Fragment {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 根据数据库中是否存在该专辑的收藏记录,来设置收藏按钮的图标显示,并更新收藏状态变量
|
|
|
|
|
|
|
|
*/
|
|
|
|
private void showLove() {
|
|
|
|
private void showLove() {
|
|
|
|
if (LitePal.where("albumId=?", mId).find(AlbumCollection.class).size() != 0) {
|
|
|
|
if (LitePal.where("albumId=?", mId).find(AlbumCollection.class).size()!= 0) {
|
|
|
|
mLove = true;
|
|
|
|
mLove = true;
|
|
|
|
mLoveBtn.setIcon(R.drawable.favorites_selected);
|
|
|
|
mLoveBtn.setIcon(R.drawable.favorites_selected);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
@ -224,6 +324,16 @@ public class AlbumContentFragment extends Fragment {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 静态工厂方法,用于创建AlbumContentFragment实例,并传入专辑相关的必要参数,
|
|
|
|
|
|
|
|
* 将参数封装到Bundle中设置给Fragment实例
|
|
|
|
|
|
|
|
* @param id 专辑的唯一标识(例如ID)
|
|
|
|
|
|
|
|
* @param albumName 专辑名称
|
|
|
|
|
|
|
|
* @param albumPic 专辑封面图片的路径或资源标识等
|
|
|
|
|
|
|
|
* @param singerName 歌手名称
|
|
|
|
|
|
|
|
* @param publicTime 专辑发行时间
|
|
|
|
|
|
|
|
* @return 返回创建好的AlbumContentFragment实例
|
|
|
|
|
|
|
|
*/
|
|
|
|
public static Fragment newInstance(String id, String albumName, String albumPic, String
|
|
|
|
public static Fragment newInstance(String id, String albumName, String albumPic, String
|
|
|
|
singerName, String publicTime) {
|
|
|
|
singerName, String publicTime) {
|
|
|
|
AlbumContentFragment albumContentFragment = new AlbumContentFragment();
|
|
|
|
AlbumContentFragment albumContentFragment = new AlbumContentFragment();
|
|
|
|
@ -237,9 +347,12 @@ public class AlbumContentFragment extends Fragment {
|
|
|
|
return albumContentFragment;
|
|
|
|
return albumContentFragment;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 从传入的Bundle中获取之前设置的专辑相关参数(如果有的话),赋值给对应的成员变量
|
|
|
|
|
|
|
|
*/
|
|
|
|
private void getBundle() {
|
|
|
|
private void getBundle() {
|
|
|
|
Bundle bundle = getArguments();
|
|
|
|
Bundle bundle = getArguments();
|
|
|
|
if (bundle != null) {
|
|
|
|
if (bundle!= null) {
|
|
|
|
mId = bundle.getString(ALBUM_ID_KEY);
|
|
|
|
mId = bundle.getString(ALBUM_ID_KEY);
|
|
|
|
mAlbumName = bundle.getString(ALBUM_NAME_KEY);
|
|
|
|
mAlbumName = bundle.getString(ALBUM_NAME_KEY);
|
|
|
|
mAlbumPic = bundle.getString(ALBUM_PIC_KEY);
|
|
|
|
mAlbumPic = bundle.getString(ALBUM_PIC_KEY);
|
|
|
|
@ -249,67 +362,132 @@ public class AlbumContentFragment extends Fragment {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 内部类,表示搜索相关的Fragment,用于处理搜索输入、显示搜索历史以及根据搜索内容切换展示不同的搜索结果页面等功能
|
|
|
|
|
|
|
|
* 这个Fragment嵌套在其他布局中使用,用于实现搜索模块的交互逻辑。
|
|
|
|
* Created by 残渊 on 2018/11/20.
|
|
|
|
* Created by 残渊 on 2018/11/20.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
public static class SearchFragment extends Fragment {
|
|
|
|
|
|
|
|
private static final String TAG = "SearchFragment";
|
|
|
|
|
|
|
|
// 用于输入搜索内容的编辑文本框
|
|
|
|
|
|
|
|
private EditText mSeekEdit;
|
|
|
|
|
|
|
|
// 用于触发搜索操作的按钮(这里是一个具有点击涟漪效果的视图)
|
|
|
|
|
|
|
|
private RippleView mSeekTv;
|
|
|
|
|
|
|
|
// 用于返回上一个页面的按钮(这里是一个具有点击涟漪效果的视图)
|
|
|
|
|
|
|
|
private RippleView mBackIv;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 创建SearchFragment的视图,加载对应的布局文件,并获取布局中的相关视图组件,
|
|
|
|
|
|
|
|
* 同时默认先显示搜索
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 内部类,表示搜索相关的Fragment,用于处理搜索输入、显示搜索历史以及根据搜索内容切换展示不同的搜索结果页面等功能
|
|
|
|
|
|
|
|
* 这个Fragment嵌套在其他布局中使用,用于实现搜索模块的交互逻辑。
|
|
|
|
|
|
|
|
* Created by 残渊 on 2018/11/20.
|
|
|
|
|
|
|
|
*/
|
|
|
|
public static class SearchFragment extends Fragment {
|
|
|
|
public static class SearchFragment extends Fragment {
|
|
|
|
private static final String TAG = "SearchFragment";
|
|
|
|
private static final String TAG = "SearchFragment";
|
|
|
|
|
|
|
|
// 用于输入搜索内容的编辑文本框
|
|
|
|
private EditText mSeekEdit;
|
|
|
|
private EditText mSeekEdit;
|
|
|
|
|
|
|
|
// 用于触发搜索操作的按钮(这里是一个具有点击涟漪效果的视图)
|
|
|
|
private RippleView mSeekTv;
|
|
|
|
private RippleView mSeekTv;
|
|
|
|
|
|
|
|
// 用于返回上一个页面的按钮(这里是一个具有点击涟漪效果的视图)
|
|
|
|
private RippleView mBackIv;
|
|
|
|
private RippleView mBackIv;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 创建SearchFragment的视图,加载对应的布局文件,并获取布局中的相关视图组件,
|
|
|
|
|
|
|
|
* 同时默认先显示搜索历史的Fragment
|
|
|
|
|
|
|
|
* @param inflater 用于将布局文件实例化为视图对象的布局填充器
|
|
|
|
|
|
|
|
* @param container 父视图容器
|
|
|
|
|
|
|
|
* @param savedInstanceState 保存的实例状态信息(如果有的话)
|
|
|
|
|
|
|
|
* @return 返回创建好的视图对象
|
|
|
|
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
|
|
Bundle savedInstanceState) {
|
|
|
|
Bundle savedInstanceState) {
|
|
|
|
|
|
|
|
// 加载fragment_search布局文件并创建视图对象
|
|
|
|
View view = inflater.inflate(R.layout.fragment_search, container, false);
|
|
|
|
View view = inflater.inflate(R.layout.fragment_search, container, false);
|
|
|
|
|
|
|
|
// 从布局中找到对应的EditText组件,用于输入搜索内容
|
|
|
|
mSeekEdit = view.findViewById(R.id.edit_seek);
|
|
|
|
mSeekEdit = view.findViewById(R.id.edit_seek);
|
|
|
|
|
|
|
|
// 从布局中找到对应的RippleView组件,作为搜索按钮
|
|
|
|
mSeekTv = view.findViewById(R.id.tv_search);
|
|
|
|
mSeekTv = view.findViewById(R.id.tv_search);
|
|
|
|
|
|
|
|
// 从布局中找到对应的RippleView组件,作为返回按钮
|
|
|
|
mBackIv = view.findViewById(R.id.iv_back);
|
|
|
|
mBackIv = view.findViewById(R.id.iv_back);
|
|
|
|
|
|
|
|
// 初始时显示搜索历史的Fragment页面
|
|
|
|
replaceFragment(new SearchHistoryFragment());
|
|
|
|
replaceFragment(new SearchHistoryFragment());
|
|
|
|
return view;
|
|
|
|
return view;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 当Fragment所在的Activity创建完成后调用,进行一些视图相关的交互设置,
|
|
|
|
|
|
|
|
* 例如弹出键盘、设置搜索按钮点击事件、编辑文本框的触摸事件以及返回按钮的点击事件等
|
|
|
|
|
|
|
|
* @param saveInstanceState 保存的实例状态信息(如果有的话)
|
|
|
|
|
|
|
|
*/
|
|
|
|
@SuppressLint("ClickableViewAccessibility")
|
|
|
|
@SuppressLint("ClickableViewAccessibility")
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void onActivityCreated(Bundle saveInstanceState) {
|
|
|
|
public void onActivityCreated(Bundle saveInstanceState) {
|
|
|
|
super.onActivityCreated(saveInstanceState);
|
|
|
|
super.onActivityCreated(saveInstanceState);
|
|
|
|
|
|
|
|
// 弹出软键盘,聚焦到搜索编辑文本框上,方便用户直接输入搜索内容
|
|
|
|
CommonUtil.showKeyboard(mSeekEdit, getActivity());
|
|
|
|
CommonUtil.showKeyboard(mSeekEdit, getActivity());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 为搜索按钮设置点击监听事件
|
|
|
|
mSeekTv.setOnClickListener(new View.OnClickListener() {
|
|
|
|
mSeekTv.setOnClickListener(new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void onClick(View v) {
|
|
|
|
public void onClick(View v) {
|
|
|
|
|
|
|
|
// 关闭软键盘,避免遮挡界面等情况
|
|
|
|
CommonUtil.closeKeybord(mSeekEdit, getActivity());
|
|
|
|
CommonUtil.closeKeybord(mSeekEdit, getActivity());
|
|
|
|
mSeekEdit.setCursorVisible(false);//隐藏光标
|
|
|
|
// 隐藏编辑文本框的光标,可能是搜索后改变显示样式需求
|
|
|
|
if(mSeekEdit.getText().toString().trim().length()==0){
|
|
|
|
mSeekEdit.setCursorVisible(false);
|
|
|
|
|
|
|
|
// 如果用户输入的内容为空(仅包含空格等也视为空),则将编辑文本框的内容设置为提示文本内容
|
|
|
|
|
|
|
|
if (mSeekEdit.getText().toString().trim().length() == 0) {
|
|
|
|
mSeekEdit.setText(mSeekEdit.getHint().toString().trim());
|
|
|
|
mSeekEdit.setText(mSeekEdit.getHint().toString().trim());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 将此次搜索内容保存到数据库中,作为搜索历史记录
|
|
|
|
saveDatabase(mSeekEdit.getText().toString());
|
|
|
|
saveDatabase(mSeekEdit.getText().toString());
|
|
|
|
|
|
|
|
// 根据输入的搜索内容,切换显示对应的搜索结果Fragment页面
|
|
|
|
replaceFragment(ContentFragment.newInstance(mSeekEdit.getText().toString()));
|
|
|
|
replaceFragment(ContentFragment.newInstance(mSeekEdit.getText().toString()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 为编辑文本框设置触摸事件监听,当用户触摸文本框时,显示光标,方便用户输入编辑
|
|
|
|
mSeekEdit.setOnTouchListener((v, event) -> {
|
|
|
|
mSeekEdit.setOnTouchListener((v, event) -> {
|
|
|
|
if (MotionEvent.ACTION_DOWN == event.getAction()) {
|
|
|
|
if (MotionEvent.ACTION_DOWN == event.getAction()) {
|
|
|
|
mSeekEdit.setCursorVisible(true);
|
|
|
|
mSeekEdit.setCursorVisible(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 为返回按钮设置点击监听事件,点击时关闭软键盘,并弹出Fragment栈,返回上一个Fragment页面
|
|
|
|
mBackIv.setOnClickListener(v -> {
|
|
|
|
mBackIv.setOnClickListener(v -> {
|
|
|
|
CommonUtil.closeKeybord(mSeekEdit,getActivity());
|
|
|
|
CommonUtil.closeKeybord(mSeekEdit, getActivity());
|
|
|
|
getActivity().getSupportFragmentManager().popBackStack();
|
|
|
|
getActivity().getSupportFragmentManager().popBackStack();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 将输入的搜索内容保存到数据库中作为搜索历史记录,先检查是否已存在相同的搜索历史,
|
|
|
|
|
|
|
|
* 如果存在则删除旧记录(可能是为了更新历史记录顺序等需求),然后再插入新的搜索历史记录
|
|
|
|
|
|
|
|
* @param seekHistory 要保存的搜索历史内容字符串
|
|
|
|
|
|
|
|
*/
|
|
|
|
private void saveDatabase(String seekHistory) {
|
|
|
|
private void saveDatabase(String seekHistory) {
|
|
|
|
|
|
|
|
// 从数据库中查询是否已存在相同的搜索历史记录
|
|
|
|
List<SearchHistory> searchHistoryList = LitePal.where("history=?", seekHistory).find(SearchHistory.class);
|
|
|
|
List<SearchHistory> searchHistoryList = LitePal.where("history=?", seekHistory).find(SearchHistory.class);
|
|
|
|
|
|
|
|
// 如果查询到有一条相同的搜索历史记录
|
|
|
|
if (searchHistoryList.size() == 1) {
|
|
|
|
if (searchHistoryList.size() == 1) {
|
|
|
|
|
|
|
|
// 删除这条已存在的旧搜索历史记录
|
|
|
|
LitePal.delete(SearchHistory.class, searchHistoryList.get(0).getId());
|
|
|
|
LitePal.delete(SearchHistory.class, searchHistoryList.get(0).getId());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 创建一个新的SearchHistory对象,用于保存此次搜索历史记录
|
|
|
|
SearchHistory searchHistory = new SearchHistory();
|
|
|
|
SearchHistory searchHistory = new SearchHistory();
|
|
|
|
searchHistory.setHistory(seekHistory);
|
|
|
|
searchHistory.setHistory(seekHistory);
|
|
|
|
|
|
|
|
// 将新的搜索历史记录保存到数据库中
|
|
|
|
searchHistory.save();
|
|
|
|
searchHistory.save();
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 用于设置编辑文本框的内容,并进行一系列相关操作,如隐藏光标、设置光标位置、关闭软键盘以及切换显示对应的搜索结果Fragment页面等
|
|
|
|
|
|
|
|
* 这个方法可以在外部调用,用于直接设置搜索内容并触发后续相关逻辑。
|
|
|
|
|
|
|
|
* @param seek 要设置的搜索内容字符串
|
|
|
|
|
|
|
|
*/
|
|
|
|
public void setSeekEdit(String seek) {
|
|
|
|
public void setSeekEdit(String seek) {
|
|
|
|
mSeekEdit.setText(seek);
|
|
|
|
mSeekEdit.setText(seek);
|
|
|
|
mSeekEdit.setCursorVisible(false);//隐藏光标
|
|
|
|
mSeekEdit.setCursorVisible(false);//隐藏光标
|
|
|
|
@ -319,6 +497,12 @@ public class AlbumContentFragment extends Fragment {
|
|
|
|
replaceFragment(ContentFragment.newInstance(mSeekEdit.getText().toString()));
|
|
|
|
replaceFragment(ContentFragment.newInstance(mSeekEdit.getText().toString()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 用于切换显示不同的Fragment页面,通过FragmentTransaction进行Fragment的替换操作,
|
|
|
|
|
|
|
|
* 将传入的Fragment替换到指定的容器布局(R.id.container)中,实现页面的切换展示效果。
|
|
|
|
|
|
|
|
* 这个方法在搜索按钮点击、设置搜索内容等情况下调用,用于更新显示搜索结果等不同的Fragment页面。
|
|
|
|
|
|
|
|
* @param fragment 要切换显示的Fragment实例
|
|
|
|
|
|
|
|
*/
|
|
|
|
//搜索后的页面
|
|
|
|
//搜索后的页面
|
|
|
|
private void replaceFragment(Fragment fragment) {
|
|
|
|
private void replaceFragment(Fragment fragment) {
|
|
|
|
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
|
|
|
|
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
|
|
|
|
@ -327,3 +511,4 @@ public class AlbumContentFragment extends Fragment {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|