This commit is contained in:
DelLevin-Home
2026-02-09 22:05:05 +08:00
parent 7dc79172fa
commit ba4aec0e08
17 changed files with 705 additions and 30 deletions

View 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;
}
}
}

View File

@@ -8,14 +8,28 @@ 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 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
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
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) {
super.onViewCreated(view, savedInstanceState);
TabLayout tabLayout = view.findViewById(R.id.tab_layout);
ViewPager2 viewPager = view.findViewById(R.id.view_pager);
tabMain = view.findViewById(R.id.tab_main);
tabSecondary = view.findViewById(R.id.tab_secondary);
viewPagerMain = view.findViewById(R.id.view_pager_main);
// 设置三标签:看过/正在看/准备看
tabLayout.addTab(tabLayout.newTab().setText("看过"));
tabLayout.addTab(tabLayout.newTab().setText("正在看"));
tabLayout.addTab(tabLayout.newTab().setText("准备看"));
// 设置外层 ViewPager2 适配器
viewPagerMain.setAdapter(new MainPagerAdapter(this));
// 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;
}
}
}

View File

@@ -12,7 +12,6 @@ import androidx.fragment.app.Fragment;
public class FragmentProfile extends Fragment {
// ⚠️ 必须有无参构造函数!
public FragmentProfile() {
// Required empty public constructor
}
@@ -33,7 +32,7 @@ public class FragmentProfile extends Fragment {
TextView movieCount = view.findViewById(R.id.tv_movie_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");
}
}

View 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);
}
}
}

View 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;
}
}

View 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;
}
}
}

View 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);
}
}
}

View 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);
}
}
}