generated from dellevin/template
1111
This commit is contained in:
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
65
app/src/main/java/top/iletter/lvnote/BookListFragment.java
Normal file
65
app/src/main/java/top/iletter/lvnote/BookListFragment.java
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package top.iletter.lvnote;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||||
|
import androidx.viewpager2.widget.ViewPager2;
|
||||||
|
|
||||||
|
import com.google.android.material.tabs.TabLayout;
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator;
|
||||||
|
|
||||||
|
public class BookListFragment extends Fragment {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
|
@Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
return inflater.inflate(R.layout.fragment_book_list, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
|
ViewPager2 viewPagerSecondary = view.findViewById(R.id.view_pager_secondary);
|
||||||
|
viewPagerSecondary.setAdapter(new SecondaryPagerAdapter(this));
|
||||||
|
|
||||||
|
TabLayout tabSecondary = requireActivity().findViewById(R.id.tab_secondary);
|
||||||
|
tabSecondary.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
new TabLayoutMediator(tabSecondary, viewPagerSecondary, (tab, position) -> {
|
||||||
|
switch (position) {
|
||||||
|
case 0: tab.setText("已读"); break;
|
||||||
|
case 1: tab.setText("在读"); break;
|
||||||
|
case 2: tab.setText("想读"); break;
|
||||||
|
}
|
||||||
|
}).attach();
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SecondaryPagerAdapter extends FragmentStateAdapter {
|
||||||
|
public SecondaryPagerAdapter(@NonNull Fragment fragment) {
|
||||||
|
super(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Fragment createFragment(int position) {
|
||||||
|
return MediaListFragment.newInstance(
|
||||||
|
position == 0 ? "read" :
|
||||||
|
position == 1 ? "reading" : "plan_to_read"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,14 +8,28 @@ import android.view.ViewGroup;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||||
import androidx.viewpager2.widget.ViewPager2;
|
import androidx.viewpager2.widget.ViewPager2;
|
||||||
|
|
||||||
import com.google.android.material.tabs.TabLayout;
|
import com.google.android.material.tabs.TabLayout;
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator;
|
||||||
|
|
||||||
public class FragmentHome extends Fragment {
|
public class FragmentHome extends Fragment {
|
||||||
|
|
||||||
|
private TabLayout tabMain;
|
||||||
|
private TabLayout tabSecondary;
|
||||||
|
private ViewPager2 viewPagerMain;
|
||||||
|
|
||||||
|
// 三个主页面
|
||||||
|
private final Fragment movieFragment = new MovieListFragment();
|
||||||
|
private final Fragment bookFragment = new BookListFragment();
|
||||||
|
private final Fragment noteFragment = new NoteListFragment();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
Bundle savedInstanceState) {
|
@Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
return inflater.inflate(R.layout.fragment_home, container, false);
|
return inflater.inflate(R.layout.fragment_home, container, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,14 +37,67 @@ public class FragmentHome extends Fragment {
|
|||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
TabLayout tabLayout = view.findViewById(R.id.tab_layout);
|
tabMain = view.findViewById(R.id.tab_main);
|
||||||
ViewPager2 viewPager = view.findViewById(R.id.view_pager);
|
tabSecondary = view.findViewById(R.id.tab_secondary);
|
||||||
|
viewPagerMain = view.findViewById(R.id.view_pager_main);
|
||||||
|
|
||||||
// 设置三标签:看过/正在看/准备看
|
// 设置外层 ViewPager2 适配器
|
||||||
tabLayout.addTab(tabLayout.newTab().setText("看过"));
|
viewPagerMain.setAdapter(new MainPagerAdapter(this));
|
||||||
tabLayout.addTab(tabLayout.newTab().setText("正在看"));
|
|
||||||
tabLayout.addTab(tabLayout.newTab().setText("准备看"));
|
|
||||||
|
|
||||||
// TODO: 后续实现 ViewPager2 适配器
|
// 绑定一级导航
|
||||||
|
new TabLayoutMediator(tabMain, viewPagerMain, (tab, position) -> {
|
||||||
|
switch (position) {
|
||||||
|
case 0:
|
||||||
|
tab.setText("观影记");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
tab.setText("书摘");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
tab.setText("随笔");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}).attach();
|
||||||
|
|
||||||
|
// 一级 Tab 切换监听(控制二级导航显示/隐藏)
|
||||||
|
tabMain.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onTabSelected(TabLayout.Tab tab) {
|
||||||
|
// 随笔页面隐藏二级导航
|
||||||
|
if (tab.getPosition() == 2) {
|
||||||
|
tabSecondary.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
tabSecondary.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTabUnselected(TabLayout.Tab tab) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTabReselected(TabLayout.Tab tab) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 外层 ViewPager2 适配器
|
||||||
|
static class MainPagerAdapter extends FragmentStateAdapter {
|
||||||
|
public MainPagerAdapter(@NonNull Fragment fragment) {
|
||||||
|
super(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Fragment createFragment(int position) {
|
||||||
|
switch (position) {
|
||||||
|
case 0: return new MovieListFragment();
|
||||||
|
case 1: return new BookListFragment();
|
||||||
|
default: return new NoteListFragment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,6 @@ import androidx.fragment.app.Fragment;
|
|||||||
|
|
||||||
public class FragmentProfile extends Fragment {
|
public class FragmentProfile extends Fragment {
|
||||||
|
|
||||||
// ⚠️ 必须有无参构造函数!
|
|
||||||
public FragmentProfile() {
|
public FragmentProfile() {
|
||||||
// Required empty public constructor
|
// Required empty public constructor
|
||||||
}
|
}
|
||||||
@@ -33,7 +32,7 @@ public class FragmentProfile extends Fragment {
|
|||||||
TextView movieCount = view.findViewById(R.id.tv_movie_count);
|
TextView movieCount = view.findViewById(R.id.tv_movie_count);
|
||||||
TextView bookCount = view.findViewById(R.id.tv_book_count);
|
TextView bookCount = view.findViewById(R.id.tv_book_count);
|
||||||
|
|
||||||
if (movieCount != null) movieCount.setText("24");
|
if (movieCount != null) movieCount.setText("14");
|
||||||
if (bookCount != null) bookCount.setText("18");
|
if (bookCount != null) bookCount.setText("18");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
52
app/src/main/java/top/iletter/lvnote/MediaAdapter.java
Normal file
52
app/src/main/java/top/iletter/lvnote/MediaAdapter.java
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package top.iletter.lvnote;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class MediaAdapter extends RecyclerView.Adapter<MediaAdapter.ViewHolder> {
|
||||||
|
|
||||||
|
private final List<String> items;
|
||||||
|
|
||||||
|
public MediaAdapter(List<String> items) {
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext())
|
||||||
|
.inflate(R.layout.item_media, parent, false);
|
||||||
|
return new ViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
|
String[] parts = items.get(position).split(" · ");
|
||||||
|
holder.title.setText(parts[0]);
|
||||||
|
holder.meta.setText(parts.length > 1 ? parts[1] + " · " + parts[2] : "");
|
||||||
|
holder.rating.setText(position % 3 == 0 ? "9.7" : position % 3 == 1 ? "9.2" : "8.9");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return items.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView title, meta, rating;
|
||||||
|
|
||||||
|
ViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
title = itemView.findViewById(R.id.tv_title);
|
||||||
|
meta = itemView.findViewById(R.id.tv_meta);
|
||||||
|
rating = itemView.findViewById(R.id.tv_rating);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
89
app/src/main/java/top/iletter/lvnote/MediaListFragment.java
Normal file
89
app/src/main/java/top/iletter/lvnote/MediaListFragment.java
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
package top.iletter.lvnote;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class MediaListFragment extends Fragment {
|
||||||
|
|
||||||
|
private static final String ARG_STATUS = "status";
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
public static MediaListFragment newInstance(String status) {
|
||||||
|
MediaListFragment fragment = new MediaListFragment();
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putString(ARG_STATUS, status);
|
||||||
|
fragment.setArguments(args);
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (getArguments() != null) {
|
||||||
|
status = getArguments().getString(ARG_STATUS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
|
@Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
return inflater.inflate(R.layout.fragment_media_list, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
|
RecyclerView recyclerView = view.findViewById(R.id.recycler_media);
|
||||||
|
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||||
|
|
||||||
|
// 模拟数据(根据状态返回不同假数据)
|
||||||
|
List<String> items = generateFakeData(status);
|
||||||
|
MediaAdapter adapter = new MediaAdapter(items);
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> generateFakeData(String status) {
|
||||||
|
List<String> data = new ArrayList<>();
|
||||||
|
switch (status) {
|
||||||
|
case "watched":
|
||||||
|
data.add("肖申克的救赎 · 弗兰克·德拉邦特 · 1994");
|
||||||
|
data.add("阿甘正传 · 罗伯特·泽米吉斯 · 1994");
|
||||||
|
data.add("盗梦空间 · 克里斯托弗·诺兰 · 2010");
|
||||||
|
break;
|
||||||
|
case "watching":
|
||||||
|
data.add("权力的游戏 S08 · HBO · 2019");
|
||||||
|
data.add("怪奇物语 S04 · Netflix · 2022");
|
||||||
|
break;
|
||||||
|
case "plan_to_watch":
|
||||||
|
data.add("奥本海默 · 克里斯托弗·诺兰 · 2023");
|
||||||
|
data.add("沙丘2 · 丹尼斯·维伦纽瓦 · 2024");
|
||||||
|
break;
|
||||||
|
case "read":
|
||||||
|
data.add("三体 · 刘慈欣 · 2006");
|
||||||
|
data.add("活着 · 余华 · 1993");
|
||||||
|
break;
|
||||||
|
case "reading":
|
||||||
|
data.add("人类简史 · 尤瓦尔·赫拉利 · 2011");
|
||||||
|
break;
|
||||||
|
case "plan_to_read":
|
||||||
|
data.add("百年孤独 · 加西亚·马尔克斯 · 1967");
|
||||||
|
data.add("追风筝的人 · 卡勒德·胡赛尼 · 2003");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
68
app/src/main/java/top/iletter/lvnote/MovieListFragment.java
Normal file
68
app/src/main/java/top/iletter/lvnote/MovieListFragment.java
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package top.iletter.lvnote;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||||
|
import androidx.viewpager2.widget.ViewPager2;
|
||||||
|
|
||||||
|
import com.google.android.material.tabs.TabLayout;
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator;
|
||||||
|
|
||||||
|
public class MovieListFragment extends Fragment {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
|
@Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
return inflater.inflate(R.layout.fragment_movie_list, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
|
ViewPager2 viewPagerSecondary = view.findViewById(R.id.view_pager_secondary);
|
||||||
|
viewPagerSecondary.setAdapter(new SecondaryPagerAdapter(this));
|
||||||
|
|
||||||
|
// 获取父 Fragment 的二级 TabLayout
|
||||||
|
TabLayout tabSecondary = requireActivity().findViewById(R.id.tab_secondary);
|
||||||
|
tabSecondary.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
// 绑定二级导航
|
||||||
|
new TabLayoutMediator(tabSecondary, viewPagerSecondary, (tab, position) -> {
|
||||||
|
switch (position) {
|
||||||
|
case 0: tab.setText("看过"); break;
|
||||||
|
case 1: tab.setText("正在看"); break;
|
||||||
|
case 2: tab.setText("准备看"); break;
|
||||||
|
}
|
||||||
|
}).attach();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 二级 ViewPager2 适配器(三个状态页面)
|
||||||
|
static class SecondaryPagerAdapter extends FragmentStateAdapter {
|
||||||
|
public SecondaryPagerAdapter(@NonNull Fragment fragment) {
|
||||||
|
super(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Fragment createFragment(int position) {
|
||||||
|
return MediaListFragment.newInstance(
|
||||||
|
position == 0 ? "watched" :
|
||||||
|
position == 1 ? "watching" : "plan_to_watch"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
53
app/src/main/java/top/iletter/lvnote/NoteAdapter.java
Normal file
53
app/src/main/java/top/iletter/lvnote/NoteAdapter.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package top.iletter.lvnote;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.ViewHolder> {
|
||||||
|
|
||||||
|
private final List<String> notes;
|
||||||
|
|
||||||
|
public NoteAdapter(List<String> notes) {
|
||||||
|
this.notes = notes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext())
|
||||||
|
.inflate(R.layout.item_note, parent, false);
|
||||||
|
return new ViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
|
String note = notes.get(position);
|
||||||
|
String[] parts = note.split(" · ");
|
||||||
|
holder.title.setText(parts[0]);
|
||||||
|
holder.content.setText(parts.length > 1 ? parts[1] : "无内容");
|
||||||
|
holder.time.setText("2024-02-09 15:30");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return notes.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView title, content, time;
|
||||||
|
|
||||||
|
ViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
title = itemView.findViewById(R.id.tv_note_title);
|
||||||
|
content = itemView.findViewById(R.id.tv_note_content);
|
||||||
|
time = itemView.findViewById(R.id.tv_note_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
app/src/main/java/top/iletter/lvnote/NoteListFragment.java
Normal file
54
app/src/main/java/top/iletter/lvnote/NoteListFragment.java
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package top.iletter.lvnote;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class NoteListFragment extends Fragment {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
|
@Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
return inflater.inflate(R.layout.fragment_note_list, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
|
RecyclerView recyclerView = view.findViewById(R.id.recycler_notes);
|
||||||
|
TextView tvEmpty = view.findViewById(R.id.tv_empty);
|
||||||
|
|
||||||
|
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||||
|
|
||||||
|
// 模拟笔记数据(空列表演示空状态)
|
||||||
|
List<String> notes = Arrays.asList(
|
||||||
|
"2024-02-09 · 今日观影笔记",
|
||||||
|
"2024-02-08 · 读书随想",
|
||||||
|
"2024-02-05 · 生活碎片"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (notes.isEmpty()) {
|
||||||
|
tvEmpty.setVisibility(View.VISIBLE);
|
||||||
|
recyclerView.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
tvEmpty.setVisibility(View.GONE);
|
||||||
|
recyclerView.setVisibility(View.VISIBLE);
|
||||||
|
NoteAdapter adapter = new NoteAdapter(notes);
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
app/src/main/res/layout/fragment_book_list.xml
Normal file
16
app/src/main/res/layout/fragment_book_list.xml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- 结构同 fragment_movie_list.xml,复用即可 -->
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
|
android:id="@+id/view_pager_secondary"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -1,28 +1,39 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<LinearLayout
|
<!-- 顶部一级导航:观影记/书摘/随笔 -->
|
||||||
|
<com.google.android.material.tabs.TabLayout
|
||||||
|
android:id="@+id/tab_main"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="48dp"
|
||||||
android:orientation="vertical"
|
app:tabMode="fixed"
|
||||||
android:padding="16dp">
|
app:tabGravity="fill"
|
||||||
|
app:tabIndicatorColor="?colorPrimary"
|
||||||
|
app:tabIndicatorHeight="3dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<!-- 分段标签 -->
|
<!-- 二级导航容器(默认隐藏)-->
|
||||||
<com.google.android.material.tabs.TabLayout
|
<com.google.android.material.tabs.TabLayout
|
||||||
android:id="@+id/tab_layout"
|
android:id="@+id/tab_secondary"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="48dp"
|
||||||
app:tabMode="fixed" />
|
android:visibility="gone"
|
||||||
|
app:tabMode="fixed"
|
||||||
|
app:tabGravity="fill"
|
||||||
|
app:tabIndicatorColor="?colorPrimary"
|
||||||
|
app:tabIndicatorHeight="2dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tab_main" />
|
||||||
|
|
||||||
<!-- 内容区域 -->
|
<!-- 内容区域:外层 ViewPager2(承载三个主页面)-->
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:id="@+id/view_pager"
|
android:id="@+id/view_pager_main"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="8dp" />
|
app:layout_constraintTop_toBottomOf="@id/tab_secondary"
|
||||||
</LinearLayout>
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
</androidx.core.widget.NestedScrollView>
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
30
app/src/main/res/layout/fragment_media_list.xml
Normal file
30
app/src/main/res/layout/fragment_media_list.xml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler_media"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
|
||||||
|
<!-- 空状态提示(可选)-->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_empty"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="暂无内容"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textColor="?colorOnSurfaceVariant"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
16
app/src/main/res/layout/fragment_movie_list.xml
Normal file
16
app/src/main/res/layout/fragment_movie_list.xml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<!-- 二级 ViewPager2(看过/正在看/准备看)-->
|
||||||
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
|
android:id="@+id/view_pager_secondary"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
31
app/src/main/res/layout/fragment_note_list.xml
Normal file
31
app/src/main/res/layout/fragment_note_list.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler_notes"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
|
||||||
|
<!-- 空状态提示 -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_empty"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="暂无笔记,点击 ➕ 添加"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textColor="?colorOnSurfaceVariant"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
70
app/src/main/res/layout/item_media.xml
Normal file
70
app/src/main/res/layout/item_media.xml
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginVertical="4dp"
|
||||||
|
app:cardElevation="1dp"
|
||||||
|
app:cardCornerRadius="8dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="12dp">
|
||||||
|
|
||||||
|
<!-- 封面占位 -->
|
||||||
|
<View
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:background="@color/md_theme_primaryContainer"
|
||||||
|
android:layout_marginEnd="12dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="影视/书籍名称"
|
||||||
|
android:textAppearance="?textAppearanceTitleMedium"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_meta"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="导演/作者 · 年份"
|
||||||
|
android:textAppearance="?textAppearanceBodySmall"
|
||||||
|
android:textColor="?colorOnSurfaceVariant"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_status"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="状态标签"
|
||||||
|
android:textAppearance="?textAppearanceLabelSmall"
|
||||||
|
android:textColor="?colorPrimary"
|
||||||
|
android:layout_marginTop="4dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- 评分 -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_rating"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="9.5"
|
||||||
|
android:textAppearance="?textAppearanceTitleSmall"
|
||||||
|
android:textColor="?colorPrimary"
|
||||||
|
android:layout_gravity="center_vertical" />
|
||||||
|
</LinearLayout>
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
46
app/src/main/res/layout/item_note.xml
Normal file
46
app/src/main/res/layout/item_note.xml
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginVertical="4dp"
|
||||||
|
app:cardElevation="1dp"
|
||||||
|
app:cardCornerRadius="12dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_note_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="笔记标题"
|
||||||
|
android:textAppearance="?textAppearanceTitleMedium"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_note_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="笔记内容预览..."
|
||||||
|
android:textAppearance="?textAppearanceBodyMedium"
|
||||||
|
android:textColor="?colorOnSurfaceVariant"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:ellipsize="end" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_note_time"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="2024-02-09 15:30"
|
||||||
|
android:textAppearance="?textAppearanceLabelSmall"
|
||||||
|
android:textColor="?colorOnSurfaceVariant"
|
||||||
|
android:layout_marginTop="8dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
@@ -12,6 +12,8 @@
|
|||||||
<string name="watched">看过</string>
|
<string name="watched">看过</string>
|
||||||
<string name="watching">正在看</string>
|
<string name="watching">正在看</string>
|
||||||
<string name="plan_to_watch">准备看</string>
|
<string name="plan_to_watch">准备看</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="add_movie">添加影视</string>
|
<string name="add_movie">添加影视</string>
|
||||||
<string name="add_book">添加书籍</string>
|
<string name="add_book">添加书籍</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user