generated from dellevin/template
222
This commit is contained in:
@@ -47,4 +47,10 @@ dependencies {
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'androidx.fragment:fragment:1.6.2'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'com.google.android.material:material:1.11.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.3.2'
|
||||
implementation 'androidx.viewpager2:viewpager2:1.0.0'
|
||||
}
|
||||
57
app/src/main/java/top/iletter/lvnote/BookAdapter.java
Normal file
57
app/src/main/java/top/iletter/lvnote/BookAdapter.java
Normal file
@@ -0,0 +1,57 @@
|
||||
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 BookAdapter extends RecyclerView.Adapter<BookAdapter.ViewHolder> {
|
||||
private final List<BookStatusFragment.BookItem> books;
|
||||
|
||||
public BookAdapter(List<BookStatusFragment.BookItem> books) {
|
||||
this.books = books;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_book, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
BookStatusFragment.BookItem book = books.get(position);
|
||||
holder.title.setText(book.title);
|
||||
holder.authors.setText(book.authors);
|
||||
holder.publisher.setText(book.publisher);
|
||||
holder.pages.setText(book.pages);
|
||||
holder.isbn.setText(book.isbn);
|
||||
holder.rating.setText(book.rating > 0 ? String.valueOf(book.rating) : "--");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return books.size();
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView title, authors, publisher, pages, isbn, rating;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
title = itemView.findViewById(R.id.tv_title);
|
||||
authors = itemView.findViewById(R.id.tv_authors);
|
||||
publisher = itemView.findViewById(R.id.tv_publisher);
|
||||
pages = itemView.findViewById(R.id.tv_pages);
|
||||
isbn = itemView.findViewById(R.id.tv_isbn);
|
||||
rating = itemView.findViewById(R.id.tv_rating);
|
||||
}
|
||||
}
|
||||
}
|
||||
100
app/src/main/java/top/iletter/lvnote/BookContainerFragment.java
Normal file
100
app/src/main/java/top/iletter/lvnote/BookContainerFragment.java
Normal file
@@ -0,0 +1,100 @@
|
||||
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.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import com.google.android.material.button.MaterialButtonToggleGroup;
|
||||
|
||||
public class BookContainerFragment extends Fragment {
|
||||
private ViewPager2 viewPager;
|
||||
private MaterialButtonToggleGroup toggleGroup;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_book_container, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
viewPager = view.findViewById(R.id.view_pager_books);
|
||||
// ✅ 修复:传入 requireActivity()
|
||||
viewPager.setAdapter(new BookPagerAdapter(requireActivity()));
|
||||
|
||||
toggleGroup = view.findViewById(R.id.toggle_books);
|
||||
|
||||
toggleGroup.addOnButtonCheckedListener((group, checkedId, isChecked) -> {
|
||||
if (isChecked) {
|
||||
int position = getPositionByButtonId(checkedId);
|
||||
viewPager.setCurrentItem(position, true);
|
||||
}
|
||||
});
|
||||
|
||||
viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
super.onPageSelected(position);
|
||||
int buttonId = getButtonIdByPosition(position);
|
||||
toggleGroup.check(buttonId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ✅ 修复:改用 if-else
|
||||
private int getPositionByButtonId(int buttonId) {
|
||||
if (buttonId == R.id.btn_read) return 0;
|
||||
if (buttonId == R.id.btn_reading) return 1;
|
||||
return 2; // btn_plan_read
|
||||
}
|
||||
|
||||
private int getButtonIdByPosition(int position) {
|
||||
if (position == 0) return R.id.btn_read;
|
||||
if (position == 1) return R.id.btn_reading;
|
||||
return R.id.btn_plan_read;
|
||||
}
|
||||
|
||||
// ✅ 修复:适配器接收 FragmentActivity
|
||||
static class BookPagerAdapter extends FragmentStateAdapter {
|
||||
public BookPagerAdapter(@NonNull FragmentActivity activity) {
|
||||
super(activity);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment createFragment(int position) {
|
||||
String status = position == 0 ? "read" :
|
||||
position == 1 ? "reading" : "plan_to_read";
|
||||
return BookStatusFragment.newInstance(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ 清理资源
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
if (viewPager != null) {
|
||||
viewPager.setAdapter(null);
|
||||
}
|
||||
if (toggleGroup != null) {
|
||||
toggleGroup.clearChecked();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
99
app/src/main/java/top/iletter/lvnote/BookStatusFragment.java
Normal file
99
app/src/main/java/top/iletter/lvnote/BookStatusFragment.java
Normal file
@@ -0,0 +1,99 @@
|
||||
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.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BookStatusFragment extends Fragment {
|
||||
private static final String ARG_STATUS = "status";
|
||||
private String status;
|
||||
|
||||
public static BookStatusFragment newInstance(String status) {
|
||||
BookStatusFragment fragment = new BookStatusFragment();
|
||||
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_book_status, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
RecyclerView recyclerView = view.findViewById(R.id.recycler_books);
|
||||
TextView tvEmpty = view.findViewById(R.id.tv_empty);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
|
||||
List<BookItem> books = generateFakeBooks(status);
|
||||
if (books.isEmpty()) {
|
||||
tvEmpty.setVisibility(View.VISIBLE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
} else {
|
||||
tvEmpty.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
recyclerView.setAdapter(new BookAdapter(books));
|
||||
}
|
||||
}
|
||||
|
||||
private List<BookItem> generateFakeBooks(String status) {
|
||||
List<BookItem> books = new ArrayList<>();
|
||||
switch (status) {
|
||||
case "read":
|
||||
books.add(new BookItem("三体", "刘慈欣", "重庆出版社", "400页", "9787229113890", 9.3f));
|
||||
books.add(new BookItem("活着", "余华", "作家出版社", "191页", "9787506365437", 9.4f));
|
||||
books.add(new BookItem("百年孤独", "加西亚·马尔克斯", "南海出版公司", "360页", "9787544253994", 9.2f));
|
||||
break;
|
||||
case "reading":
|
||||
books.add(new BookItem("人类简史", "尤瓦尔·赫拉利", "中信出版社", "424页", "9787508647357", 8.9f));
|
||||
books.add(new BookItem("三体Ⅱ:黑暗森林", "刘慈欣", "重庆出版社", "450页", "9787229113906", 9.2f));
|
||||
break;
|
||||
case "plan_to_read":
|
||||
books.add(new BookItem("追风筝的人", "卡勒德·胡赛尼", "上海人民出版社", "362页", "9787208061644", 0));
|
||||
books.add(new BookItem("小王子", "安托万·德·圣-埃克苏佩里", "天津人民出版社", "96页", "9787201076490", 0));
|
||||
break;
|
||||
}
|
||||
return books;
|
||||
}
|
||||
|
||||
public static class BookItem {
|
||||
public String title, authors, publisher, pages, isbn;
|
||||
public float rating;
|
||||
|
||||
public BookItem(String title, String authors, String publisher,
|
||||
String pages, String isbn, float rating) {
|
||||
this.title = title;
|
||||
this.authors = authors;
|
||||
this.publisher = publisher;
|
||||
this.pages = pages;
|
||||
this.isbn = isbn;
|
||||
this.rating = rating;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
@@ -15,16 +16,8 @@ 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(@NonNull LayoutInflater inflater,
|
||||
@@ -37,60 +30,33 @@ public class FragmentHome extends Fragment {
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
tabMain = view.findViewById(R.id.tab_main);
|
||||
tabSecondary = view.findViewById(R.id.tab_secondary);
|
||||
viewPagerMain = view.findViewById(R.id.view_pager_main);
|
||||
TabLayout tabMain = view.findViewById(R.id.tab_main);
|
||||
|
||||
// 设置外层 ViewPager2 适配器
|
||||
viewPagerMain.setAdapter(new MainPagerAdapter(this));
|
||||
// 修复嵌套崩溃
|
||||
viewPagerMain.setAdapter(new MainPagerAdapter(requireActivity()));
|
||||
|
||||
// 绑定一级导航
|
||||
// 绑定导航
|
||||
new TabLayoutMediator(tabMain, viewPagerMain, (tab, position) -> {
|
||||
switch (position) {
|
||||
case 0:
|
||||
tab.setText("观影记");
|
||||
break;
|
||||
case 1:
|
||||
tab.setText("书摘");
|
||||
break;
|
||||
case 2:
|
||||
tab.setText("随笔");
|
||||
break;
|
||||
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);
|
||||
public MainPagerAdapter(@NonNull FragmentActivity activity) {
|
||||
super(activity);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment createFragment(int position) {
|
||||
switch (position) {
|
||||
case 0: return new MovieListFragment();
|
||||
case 1: return new BookListFragment();
|
||||
case 0: return new MovieContainerFragment();
|
||||
case 1: return new BookContainerFragment();
|
||||
default: return new NoteListFragment();
|
||||
}
|
||||
}
|
||||
@@ -100,4 +66,12 @@ public class FragmentHome extends Fragment {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
if (viewPagerMain != null) {
|
||||
viewPagerMain.setAdapter(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,8 @@ import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
public class FragmentProfile extends Fragment {
|
||||
|
||||
public FragmentProfile() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
// ✅ 必须有无参构造函数
|
||||
public FragmentProfile() {}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@@ -27,12 +25,9 @@ public class FragmentProfile extends Fragment {
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
// 安全地操作 View
|
||||
TextView movieCount = view.findViewById(R.id.tv_movie_count);
|
||||
TextView bookCount = view.findViewById(R.id.tv_book_count);
|
||||
|
||||
if (movieCount != null) movieCount.setText("14");
|
||||
if (movieCount != null) movieCount.setText("24");
|
||||
if (bookCount != null) bookCount.setText("18");
|
||||
}
|
||||
}
|
||||
@@ -1,66 +1,61 @@
|
||||
package top.iletter.lvnote;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.google.android.material.bottomappbar.BottomAppBar;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
private FragmentHome homeFragment = new FragmentHome();
|
||||
private FragmentProfile profileFragment = new FragmentProfile();
|
||||
private Fragment currentFragment = homeFragment;
|
||||
private FragmentHome homeFragment;
|
||||
private FragmentProfile profileFragment;
|
||||
private Fragment currentFragment;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
// 初始化默认显示主页
|
||||
// ✅ 一次性创建 Fragment,永不销毁
|
||||
if (savedInstanceState == null) {
|
||||
homeFragment = new FragmentHome();
|
||||
profileFragment = new FragmentProfile();
|
||||
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.fragment_container, homeFragment)
|
||||
.add(R.id.fragment_container, homeFragment, "home") // 添加主页
|
||||
.add(R.id.fragment_container, profileFragment, "profile") // 添加我的
|
||||
.hide(profileFragment) // 默认隐藏"我的"
|
||||
.commit();
|
||||
currentFragment = homeFragment;
|
||||
} else {
|
||||
// 从 savedInstanceState 恢复(横竖屏切换等场景)
|
||||
homeFragment = (FragmentHome) getSupportFragmentManager().findFragmentByTag("home");
|
||||
profileFragment = (FragmentProfile) getSupportFragmentManager().findFragmentByTag("profile");
|
||||
currentFragment = homeFragment;
|
||||
}
|
||||
|
||||
// 左按钮:主页
|
||||
// 底部导航按钮
|
||||
ImageButton btnHome = findViewById(R.id.btn_home);
|
||||
btnHome.setOnClickListener(v -> switchFragment(homeFragment));
|
||||
|
||||
// 右按钮:我的
|
||||
ImageButton btnProfile = findViewById(R.id.btn_profile);
|
||||
btnProfile.setOnClickListener(v -> switchFragment(profileFragment));
|
||||
|
||||
// 中间按钮:添加
|
||||
FloatingActionButton fabAdd = findViewById(R.id.fab_add);
|
||||
fabAdd.setOnClickListener(v -> {
|
||||
// TODO: 跳转到新增页面
|
||||
Toast.makeText(this, "点击了添加按钮", Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
fabAdd.setOnClickListener(v ->
|
||||
Toast.makeText(this, "点击了添加按钮", Toast.LENGTH_SHORT).show()
|
||||
);
|
||||
}
|
||||
|
||||
// ✅ 核心修复:用 show()/hide() 替代 replace()
|
||||
private void switchFragment(Fragment targetFragment) {
|
||||
if (currentFragment != targetFragment) {
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.setCustomAnimations(
|
||||
android.R.anim.fade_in,
|
||||
android.R.anim.fade_out,
|
||||
android.R.anim.fade_in,
|
||||
android.R.anim.fade_out
|
||||
)
|
||||
.replace(R.id.fragment_container, targetFragment)
|
||||
.hide(currentFragment) // 隐藏当前
|
||||
.show(targetFragment) // 显示目标
|
||||
.commit();
|
||||
currentFragment = targetFragment;
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
59
app/src/main/java/top/iletter/lvnote/MovieAdapter.java
Normal file
59
app/src/main/java/top/iletter/lvnote/MovieAdapter.java
Normal file
@@ -0,0 +1,59 @@
|
||||
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 MovieAdapter extends RecyclerView.Adapter<MovieAdapter.ViewHolder> {
|
||||
private final List<MovieStatusFragment.MovieItem> movies;
|
||||
|
||||
public MovieAdapter(List<MovieStatusFragment.MovieItem> movies) {
|
||||
this.movies = movies;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_movie, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
MovieStatusFragment.MovieItem movie = movies.get(position);
|
||||
holder.title.setText(movie.title);
|
||||
holder.directors.setText("导演:" + movie.directors);
|
||||
holder.actors.setText("主演:" + movie.actors);
|
||||
holder.duration.setText(movie.duration);
|
||||
holder.region.setText(movie.region);
|
||||
holder.year.setText(movie.year);
|
||||
holder.rating.setText(movie.rating > 0 ? String.valueOf(movie.rating) : "--");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return movies.size();
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView title, directors, actors, duration, region, year, rating;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
title = itemView.findViewById(R.id.tv_title);
|
||||
directors = itemView.findViewById(R.id.tv_directors);
|
||||
actors = itemView.findViewById(R.id.tv_actors);
|
||||
duration = itemView.findViewById(R.id.tv_duration);
|
||||
region = itemView.findViewById(R.id.tv_region);
|
||||
year = itemView.findViewById(R.id.tv_year);
|
||||
rating = itemView.findViewById(R.id.tv_rating);
|
||||
}
|
||||
}
|
||||
}
|
||||
102
app/src/main/java/top/iletter/lvnote/MovieContainerFragment.java
Normal file
102
app/src/main/java/top/iletter/lvnote/MovieContainerFragment.java
Normal file
@@ -0,0 +1,102 @@
|
||||
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.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import com.google.android.material.button.MaterialButtonToggleGroup;
|
||||
|
||||
public class MovieContainerFragment extends Fragment {
|
||||
private ViewPager2 viewPager;
|
||||
private MaterialButtonToggleGroup toggleGroup;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_movie_container, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
viewPager = view.findViewById(R.id.view_pager_movies);
|
||||
// ✅ 修复:传入 requireActivity()
|
||||
viewPager.setAdapter(new MoviePagerAdapter(requireActivity()));
|
||||
|
||||
toggleGroup = view.findViewById(R.id.toggle_movies);
|
||||
|
||||
// 按钮点击 → 切换 ViewPager
|
||||
toggleGroup.addOnButtonCheckedListener((group, checkedId, isChecked) -> {
|
||||
if (isChecked) {
|
||||
int position = getPositionByButtonId(checkedId);
|
||||
viewPager.setCurrentItem(position, true);
|
||||
}
|
||||
});
|
||||
|
||||
// ViewPager 滑动 → 更新按钮选中状态
|
||||
viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
super.onPageSelected(position);
|
||||
int buttonId = getButtonIdByPosition(position);
|
||||
toggleGroup.check(buttonId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ✅ 修复:改用 if-else(避免 R.id 非常量问题)
|
||||
private int getPositionByButtonId(int buttonId) {
|
||||
if (buttonId == R.id.btn_watched) return 0;
|
||||
if (buttonId == R.id.btn_watching) return 1;
|
||||
return 2; // btn_plan
|
||||
}
|
||||
|
||||
private int getButtonIdByPosition(int position) {
|
||||
if (position == 0) return R.id.btn_watched;
|
||||
if (position == 1) return R.id.btn_watching;
|
||||
return R.id.btn_plan;
|
||||
}
|
||||
|
||||
// ✅ 修复:适配器接收 FragmentActivity
|
||||
static class MoviePagerAdapter extends FragmentStateAdapter {
|
||||
public MoviePagerAdapter(@NonNull FragmentActivity activity) {
|
||||
super(activity);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment createFragment(int position) {
|
||||
String status = position == 0 ? "watched" :
|
||||
position == 1 ? "watching" : "plan_to_watch";
|
||||
return MovieStatusFragment.newInstance(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ 清理资源
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
if (viewPager != null) {
|
||||
viewPager.setAdapter(null);
|
||||
}
|
||||
if (toggleGroup != null) {
|
||||
toggleGroup.clearChecked();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
107
app/src/main/java/top/iletter/lvnote/MovieStatusFragment.java
Normal file
107
app/src/main/java/top/iletter/lvnote/MovieStatusFragment.java
Normal file
@@ -0,0 +1,107 @@
|
||||
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.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MovieStatusFragment extends Fragment {
|
||||
private static final String ARG_STATUS = "status";
|
||||
private String status;
|
||||
|
||||
public static MovieStatusFragment newInstance(String status) {
|
||||
MovieStatusFragment fragment = new MovieStatusFragment();
|
||||
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_movie_status, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
RecyclerView recyclerView = view.findViewById(R.id.recycler_movies);
|
||||
TextView tvEmpty = view.findViewById(R.id.tv_empty);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
|
||||
List<MovieItem> items = generateFakeMovies(status);
|
||||
if (items.isEmpty()) {
|
||||
tvEmpty.setVisibility(View.VISIBLE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
} else {
|
||||
tvEmpty.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
recyclerView.setAdapter(new MovieAdapter(items));
|
||||
}
|
||||
}
|
||||
|
||||
private List<MovieItem> generateFakeMovies(String status) {
|
||||
List<MovieItem> movies = new ArrayList<>();
|
||||
switch (status) {
|
||||
case "watched":
|
||||
movies.add(new MovieItem("肖申克的救赎", "弗兰克·德拉邦特",
|
||||
"蒂姆·罗宾斯, 摩根·弗里曼", "142min", "美国", "1994", 9.7f));
|
||||
movies.add(new MovieItem("阿甘正传", "罗伯特·泽米吉斯",
|
||||
"汤姆·汉克斯, 罗宾·怀特", "142min", "美国", "1994", 9.5f));
|
||||
movies.add(new MovieItem("盗梦空间", "克里斯托弗·诺兰",
|
||||
"莱昂纳多·迪卡普里奥", "148min", "美国", "2010", 9.3f));
|
||||
break;
|
||||
case "watching":
|
||||
movies.add(new MovieItem("奥本海默", "克里斯托弗·诺兰",
|
||||
"基里安·墨菲, 艾米莉·布朗特", "180min", "美国", "2023", 8.9f));
|
||||
movies.add(new MovieItem("沙丘", "丹尼斯·维伦纽瓦",
|
||||
"提莫西·查拉梅, 赞达亚", "155min", "美国", "2021", 8.0f));
|
||||
break;
|
||||
case "plan_to_watch":
|
||||
movies.add(new MovieItem("沙丘2", "丹尼斯·维伦纽瓦",
|
||||
"提莫西·查拉梅, 赞达亚", "166min", "美国", "2024", 0));
|
||||
movies.add(new MovieItem("疯狂的麦克斯:狂暴女神", "乔治·米勒",
|
||||
"安雅·泰勒-乔伊", "140min", "澳大利亚", "2024", 0));
|
||||
break;
|
||||
}
|
||||
return movies;
|
||||
}
|
||||
|
||||
public static class MovieItem {
|
||||
public String title, directors, actors, duration, region, year;
|
||||
public float rating;
|
||||
|
||||
public MovieItem(String title, String directors, String actors,
|
||||
String duration, String region, String year, float rating) {
|
||||
this.title = title;
|
||||
this.directors = directors;
|
||||
this.actors = actors;
|
||||
this.duration = duration;
|
||||
this.region = region;
|
||||
this.year = year;
|
||||
this.rating = rating;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,9 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
import java.util.List;
|
||||
|
||||
public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.ViewHolder> {
|
||||
private final List<NoteListFragment.NoteItem> notes;
|
||||
|
||||
private final List<String> notes;
|
||||
|
||||
public NoteAdapter(List<String> notes) {
|
||||
public NoteAdapter(List<NoteListFragment.NoteItem> notes) {
|
||||
this.notes = notes;
|
||||
}
|
||||
|
||||
@@ -28,11 +27,10 @@ public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.ViewHolder> {
|
||||
|
||||
@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");
|
||||
NoteListFragment.NoteItem note = notes.get(position);
|
||||
holder.title.setText(note.title);
|
||||
holder.content.setText(note.content);
|
||||
holder.time.setText(note.time);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,9 +43,9 @@ public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.ViewHolder> {
|
||||
|
||||
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);
|
||||
title = itemView.findViewById(R.id.tv_title);
|
||||
content = itemView.findViewById(R.id.tv_content);
|
||||
time = itemView.findViewById(R.id.tv_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,11 +12,10 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NoteListFragment extends Fragment {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
@@ -31,24 +30,40 @@ public class NoteListFragment extends Fragment {
|
||||
|
||||
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 · 生活碎片"
|
||||
);
|
||||
|
||||
List<NoteItem> notes = generateFakeNotes();
|
||||
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);
|
||||
recyclerView.setAdapter(new NoteAdapter(notes));
|
||||
}
|
||||
}
|
||||
|
||||
private List<NoteItem> generateFakeNotes() {
|
||||
List<NoteItem> notes = new ArrayList<>();
|
||||
notes.add(new NoteItem("观影笔记:肖申克的救赎",
|
||||
"有些鸟是关不住的,它们的羽毛太鲜亮了。当它们飞走的时候,你心底里知道把它们关起来是一种罪恶,也是一种遗憾。",
|
||||
"02-09 15:30"));
|
||||
notes.add(new NoteItem("读书随想:三体",
|
||||
"给岁月以文明,而不是给文明以岁月。黑暗森林法则揭示了宇宙社会学的残酷真相。",
|
||||
"02-08 20:15"));
|
||||
notes.add(new NoteItem("生活碎片",
|
||||
"济南的冬天,阳光透过梧桐叶洒在市中区的老街上,时间仿佛慢了下来。",
|
||||
"02-07 09:45"));
|
||||
return notes;
|
||||
}
|
||||
|
||||
public static class NoteItem {
|
||||
public String title, content, time;
|
||||
|
||||
public NoteItem(String title, String content, String time) {
|
||||
this.title = title;
|
||||
this.content = content;
|
||||
this.time = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
5
app/src/main/res/color/segmented_button_bg.xml
Normal file
5
app/src/main/res/color/segmented_button_bg.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_checked="true" android:color="@color/md_theme_primary" />
|
||||
<item android:color="@android:color/transparent" />
|
||||
</selector>
|
||||
7
app/src/main/res/color/segmented_button_text.xml
Normal file
7
app/src/main/res/color/segmented_button_text.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- 选中状态:白色文字 -->
|
||||
<item android:state_checked="true" android:color="@android:color/white" />
|
||||
<!-- 未选中状态:主色文字 -->
|
||||
<item android:color="?attr/colorPrimary" />
|
||||
</selector>
|
||||
@@ -4,6 +4,8 @@
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorOnSurfaceVariant"
|
||||
android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z" />
|
||||
android:fillColor="@android:color/transparent"
|
||||
android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z"
|
||||
android:strokeColor="?attr/colorOnSurfaceVariant"
|
||||
android:strokeWidth="2" />
|
||||
</vector>
|
||||
@@ -4,6 +4,8 @@
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorOnSurfaceVariant"
|
||||
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z" />
|
||||
android:fillColor="@android:color/transparent"
|
||||
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"
|
||||
android:strokeColor="?attr/colorOnSurfaceVariant"
|
||||
android:strokeWidth="2" />
|
||||
</vector>
|
||||
@@ -5,29 +5,28 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!-- 内容区域(三个 Fragment 的容器)-->
|
||||
<!-- 内容区域 -->
|
||||
<FrameLayout
|
||||
android:id="@+id/fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/bottom_nav"
|
||||
android:background="?android:attr/windowBackground" />
|
||||
app:layout_constraintBottom_toTopOf="@id/bottom_nav" />
|
||||
|
||||
<!-- 底部导航栏(三个平级按钮)-->
|
||||
<!-- 底部三按钮导航 -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/bottom_nav"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:cardElevation="4dp"
|
||||
app:cardCornerRadius="0dp"
|
||||
android:layout_margin="8dp">
|
||||
app:cardElevation="2dp"
|
||||
app:cardCornerRadius="0dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!-- 左:主页 -->
|
||||
<ImageButton
|
||||
android:id="@+id/btn_home"
|
||||
android:layout_width="0dp"
|
||||
@@ -52,25 +51,28 @@
|
||||
app:layout_constraintEnd_toEndOf="@id/btn_home"
|
||||
android:layout_marginTop="4dp" />
|
||||
|
||||
<!-- 中:加号 -->
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab_add"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginTop="-12dp"
|
||||
android:src="@drawable/ic_add"
|
||||
app:borderWidth="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.498"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:borderWidth="0dp"
|
||||
app:tint="@android:color/white" />
|
||||
|
||||
<!-- 右:我的 -->
|
||||
<ImageButton
|
||||
android:id="@+id/btn_profile"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_person"
|
||||
android:tint="?attr/colorOnSurfaceVariant"
|
||||
app:layout_constraintWidth_percent="0.33"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
@@ -87,8 +89,6 @@
|
||||
app:layout_constraintStart_toStartOf="@id/btn_profile"
|
||||
app:layout_constraintEnd_toEndOf="@id/btn_profile"
|
||||
android:layout_marginTop="4dp" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
61
app/src/main/res/layout/fragment_book_container.xml
Normal file
61
app/src/main/res/layout/fragment_book_container.xml
Normal file
@@ -0,0 +1,61 @@
|
||||
<?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">
|
||||
|
||||
<!-- 书籍按钮式导航 -->
|
||||
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||
android:id="@+id/toggle_books"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:singleSelection="true"
|
||||
app:selectionRequired="true"
|
||||
app:checkedButton="@id/btn_read"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_read"
|
||||
style="@style/Widget.Lvnote.SegmentedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:text="已读"
|
||||
app:cornerRadius="18dp"
|
||||
app:strokeWidth="1dp"
|
||||
app:strokeColor="?colorPrimary" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_reading"
|
||||
style="@style/Widget.Lvnote.SegmentedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:text="在读"
|
||||
app:cornerRadius="0dp"
|
||||
app:strokeWidth="1dp"
|
||||
app:strokeColor="?colorPrimary" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_plan_read"
|
||||
style="@style/Widget.Lvnote.SegmentedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:text="想读"
|
||||
app:cornerRadius="18dp"
|
||||
app:strokeWidth="1dp"
|
||||
app:strokeColor="?colorPrimary" />
|
||||
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/view_pager_books"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/toggle_books"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,16 +0,0 @@
|
||||
<?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>
|
||||
@@ -4,22 +4,22 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp">
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="12dp">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_media"
|
||||
android:id="@+id/recycler_books"
|
||||
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:text="暂无书籍记录"
|
||||
android:textSize="16sp"
|
||||
android:textColor="?colorOnSurfaceVariant"
|
||||
android:visibility="gone"
|
||||
@@ -5,35 +5,30 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!-- 顶部一级导航:观影记/书摘/随笔 -->
|
||||
<!-- ✅ 紧凑靠左导航:scrollable + start + 小内边距 -->
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tab_main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
app:tabMode="fixed"
|
||||
app:tabGravity="fill"
|
||||
app:tabIndicatorColor="?colorPrimary"
|
||||
app:tabIndicatorHeight="3dp"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<!-- 二级导航容器(默认隐藏)-->
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tab_secondary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:visibility="gone"
|
||||
app:tabMode="fixed"
|
||||
app:tabGravity="fill"
|
||||
app:tabIndicatorColor="?colorPrimary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:tabMode="scrollable"
|
||||
app:tabGravity="start"
|
||||
app:tabIndicatorHeight="2dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/tab_main" />
|
||||
app:tabIndicatorColor="?colorPrimary"
|
||||
app:tabPaddingStart="8dp"
|
||||
app:tabPaddingEnd="8dp"
|
||||
app:tabTextAppearance="@style/TextAppearance.Lvnote.Tab.Unselected"
|
||||
app:tabSelectedTextAppearance="@style/TextAppearance.Lvnote.Tab.Selected"
|
||||
app:tabRippleColor="@null"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<!-- 内容区域:外层 ViewPager2(承载三个主页面)-->
|
||||
<!-- 内容区域 -->
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/view_pager_main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/tab_secondary"
|
||||
app:layout_constraintTop_toBottomOf="@id/tab_main"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
57
app/src/main/res/layout/fragment_movie_container.xml
Normal file
57
app/src/main/res/layout/fragment_movie_container.xml
Normal file
@@ -0,0 +1,57 @@
|
||||
<?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:paddingTop="12dp">
|
||||
|
||||
<!-- 精致按钮式二级导航 -->
|
||||
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||
android:id="@+id/toggle_movies"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:singleSelection="true"
|
||||
app:selectionRequired="true"
|
||||
app:checkedButton="@id/btn_watched"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
|
||||
<!-- 左按钮:圆角左侧 -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_watched"
|
||||
style="@style/Widget.Lvnote.SegmentedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="36dp"
|
||||
android:text="已看"
|
||||
app:cornerRadius="18dp" />
|
||||
|
||||
<!-- 中按钮:无圆角(直角拼接)-->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_watching"
|
||||
style="@style/Widget.Lvnote.SegmentedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="36dp"
|
||||
android:text="在看"
|
||||
app:cornerRadius="0dp" />
|
||||
|
||||
<!-- 右按钮:圆角右侧 -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_plan"
|
||||
style="@style/Widget.Lvnote.SegmentedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="36dp"
|
||||
android:text="想看"
|
||||
app:cornerRadius="18dp" />
|
||||
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/view_pager_movies"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="24dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/toggle_movies"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,16 +0,0 @@
|
||||
<?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>
|
||||
30
app/src/main/res/layout/fragment_movie_status.xml
Normal file
30
app/src/main/res/layout/fragment_movie_status.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:paddingHorizontal="16dp"
|
||||
android:paddingVertical="12dp">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_movies"
|
||||
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>
|
||||
@@ -14,12 +14,11 @@
|
||||
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:text="暂无笔记,点击 ➕ 记录灵感"
|
||||
android:textSize="16sp"
|
||||
android:textColor="?colorOnSurfaceVariant"
|
||||
android:visibility="visible"
|
||||
@@ -27,5 +26,4 @@
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -9,24 +9,10 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- 个人信息卡片 -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardElevation="2dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:padding="24dp"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<!-- 圆形头像(用 bg_circle 背景实现)-->
|
||||
<!-- 圆形头像(用纯色背景替代 CircleImageView)-->
|
||||
<View
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
@@ -36,17 +22,15 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Levin"
|
||||
android:textAppearance="?textAppearanceTitleMedium"
|
||||
android:layout_marginTop="12dp" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
android:textAppearance="?textAppearanceTitleLarge"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
<!-- 统计信息 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center">
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="32dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
@@ -59,16 +43,16 @@
|
||||
android:id="@+id/tv_movie_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="24"
|
||||
android:textAppearance="?textAppearanceDisplaySmall"
|
||||
android:text="0"
|
||||
android:textAppearance="?textAppearanceDisplayMedium"
|
||||
android:textColor="?colorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/movies_watched"
|
||||
android:textAppearance="?textAppearanceLabelMedium"
|
||||
android:layout_marginTop="4dp" />
|
||||
android:textAppearance="?textAppearanceLabelLarge"
|
||||
android:layout_marginTop="8dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
@@ -82,16 +66,16 @@
|
||||
android:id="@+id/tv_book_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="18"
|
||||
android:textAppearance="?textAppearanceDisplaySmall"
|
||||
android:text="0"
|
||||
android:textAppearance="?textAppearanceDisplayMedium"
|
||||
android:textColor="?colorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/books_read"
|
||||
android:textAppearance="?textAppearanceLabelMedium"
|
||||
android:layout_marginTop="4dp" />
|
||||
android:textAppearance="?textAppearanceLabelLarge"
|
||||
android:layout_marginTop="8dp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
120
app/src/main/res/layout/item_book.xml
Normal file
120
app/src/main/res/layout/item_book.xml
Normal file
@@ -0,0 +1,120 @@
|
||||
<?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="8dp"
|
||||
app:cardElevation="0dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:strokeWidth="1px"
|
||||
app:strokeColor="?colorOutlineVariant">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<View
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="90dp"
|
||||
android:background="@color/md_theme_secondaryContainer"
|
||||
android:layout_marginEnd="16dp" />
|
||||
|
||||
<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_authors"
|
||||
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_publisher"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="重庆出版社"
|
||||
android:textAppearance="?textAppearanceBodySmall"
|
||||
android:textColor="?colorOnSurfaceVariant"
|
||||
android:layout_marginTop="2dp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_pages"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="400页"
|
||||
android:textAppearance="?textAppearanceLabelSmall"
|
||||
android:textColor="?colorOnSurfaceVariant"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:paddingVertical="4dp"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_isbn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="9787229113890"
|
||||
android:textAppearance="?textAppearanceLabelSmall"
|
||||
android:textColor="?colorOnSurfaceVariant"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:paddingVertical="4dp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="end"
|
||||
android:layout_gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_rating"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="9.3"
|
||||
android:textAppearance="?textAppearanceTitleSmall"
|
||||
android:textColor="?colorPrimary"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="豆瓣"
|
||||
android:textAppearance="?textAppearanceLabelSmall"
|
||||
android:textColor="?colorOnSurfaceVariant"
|
||||
android:layout_marginTop="4dp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
@@ -1,70 +0,0 @@
|
||||
<?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>
|
||||
130
app/src/main/res/layout/item_movie.xml
Normal file
130
app/src/main/res/layout/item_movie.xml
Normal file
@@ -0,0 +1,130 @@
|
||||
<?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="8dp"
|
||||
app:cardElevation="0dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:strokeWidth="1px"
|
||||
app:strokeColor="?colorOutlineVariant">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<View
|
||||
android:layout_width="70dp"
|
||||
android:layout_height="96dp"
|
||||
android:background="@color/md_theme_primaryContainer"
|
||||
android:layout_marginEnd="16dp" />
|
||||
|
||||
<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_directors"
|
||||
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_actors"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="主演:蒂姆·罗宾斯, 摩根·弗里曼"
|
||||
android:textAppearance="?textAppearanceBodySmall"
|
||||
android:textColor="?colorOnSurfaceVariant"
|
||||
android:layout_marginTop="2dp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_duration"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="142min"
|
||||
android:textAppearance="?textAppearanceLabelSmall"
|
||||
android:textColor="?colorOnSurfaceVariant"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:paddingVertical="4dp"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_region"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="美国"
|
||||
android:textAppearance="?textAppearanceLabelSmall"
|
||||
android:textColor="?colorOnSurfaceVariant"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:paddingVertical="4dp"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_year"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="1994"
|
||||
android:textAppearance="?textAppearanceLabelSmall"
|
||||
android:textColor="?colorOnSurfaceVariant"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:paddingVertical="4dp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="end"
|
||||
android:layout_gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_rating"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="9.7"
|
||||
android:textAppearance="?textAppearanceTitleSmall"
|
||||
android:textColor="?colorPrimary"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="IMDb"
|
||||
android:textAppearance="?textAppearanceLabelSmall"
|
||||
android:textColor="?colorOnSurfaceVariant"
|
||||
android:layout_marginTop="4dp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
@@ -4,43 +4,52 @@
|
||||
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">
|
||||
android:layout_marginVertical="10dp"
|
||||
app:cardElevation="0dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:strokeWidth="1px"
|
||||
app:strokeColor="?colorOutlineVariant">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
android:padding="18dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_note_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="笔记标题"
|
||||
android:text="观影笔记:肖申克的救赎"
|
||||
android:textAppearance="?textAppearanceTitleMedium"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_note_content"
|
||||
android:id="@+id/tv_time"
|
||||
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:text="02-09 15:30"
|
||||
android:textAppearance="?textAppearanceLabelSmall"
|
||||
android:textColor="?colorOnSurfaceVariant"
|
||||
android:layout_marginTop="8dp" />
|
||||
android:layout_marginStart="12dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="有些鸟是关不住的,它们的羽毛太鲜亮了..."
|
||||
android:textAppearance="?textAppearanceBodyMedium"
|
||||
android:textColor="?colorOnSurface"
|
||||
android:layout_marginTop="12dp"
|
||||
android:maxLines="3"
|
||||
android:ellipsize="end" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Material 3 Seed Color: Blue -->
|
||||
<!-- Material 3 蓝色主题 -->
|
||||
<color name="md_theme_primary">#4157FF</color>
|
||||
<color name="md_theme_onPrimary">#FFFFFF</color>
|
||||
<color name="md_theme_primaryContainer">#DDE1FF</color>
|
||||
@@ -10,12 +11,9 @@
|
||||
<color name="md_theme_onSecondaryContainer">#171A2C</color>
|
||||
<color name="md_theme_tertiary">#7A5573</color>
|
||||
<color name="md_theme_onTertiary">#FFFFFF</color>
|
||||
<color name="md_theme_tertiaryContainer">#FFD7F2</color>
|
||||
<color name="md_theme_onTertiaryContainer">#2F1229</color>
|
||||
<color name="md_theme_error">#BA1A1A</color>
|
||||
<color name="md_theme_onError">#FFFFFF</color>
|
||||
<color name="md_theme_errorContainer">#FFDAD6</color>
|
||||
<color name="md_theme_onErrorContainer">#410002</color>
|
||||
<color name="md_theme_onError">#FFFFFF</color>
|
||||
<color name="md_theme_background">#FEFBFF</color>
|
||||
<color name="md_theme_onBackground">#1B1B1F</color>
|
||||
<color name="md_theme_surface">#FEFBFF</color>
|
||||
@@ -24,7 +22,4 @@
|
||||
<color name="md_theme_onSurfaceVariant">#46464F</color>
|
||||
<color name="md_theme_outline">#777680</color>
|
||||
<color name="md_theme_outlineVariant">#C7C5D0</color>
|
||||
<color name="md_theme_inverseSurface">#303033</color>
|
||||
<color name="md_theme_inverseOnSurface">#F3F0F4</color>
|
||||
<color name="md_theme_inversePrimary">#BAC5FF</color>
|
||||
</resources>
|
||||
@@ -1,19 +1,8 @@
|
||||
<resources>
|
||||
<string name="app_name">已阅</string>
|
||||
<string name="app_name">LvNote</string>
|
||||
<string name="home">主页</string>
|
||||
<string name="profile">我的</string>
|
||||
<string name="add_media">添加</string>
|
||||
|
||||
<!-- 👇 新增:修复编译错误 -->
|
||||
<string name="movies_watched">影视</string>
|
||||
<string name="books_read">书籍</string>
|
||||
|
||||
<!-- 可选:后续可能用到的字符串 -->
|
||||
<string name="watched">看过</string>
|
||||
<string name="watching">正在看</string>
|
||||
<string name="plan_to_watch">准备看</string>
|
||||
|
||||
|
||||
<string name="add_movie">添加影视</string>
|
||||
<string name="add_book">添加书籍</string>
|
||||
</resources>
|
||||
@@ -1,7 +1,6 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- 必须保留这个名字:Theme.Lvnote -->
|
||||
<!-- 主题 -->
|
||||
<style name="Theme.Lvnote" parent="Theme.Material3.DayNight">
|
||||
<!-- Material 3 颜色 -->
|
||||
<item name="colorPrimary">@color/md_theme_primary</item>
|
||||
<item name="colorOnPrimary">@color/md_theme_onPrimary</item>
|
||||
<item name="colorPrimaryContainer">@color/md_theme_primaryContainer</item>
|
||||
@@ -10,14 +9,6 @@
|
||||
<item name="colorOnSecondary">@color/md_theme_onSecondary</item>
|
||||
<item name="colorSecondaryContainer">@color/md_theme_secondaryContainer</item>
|
||||
<item name="colorOnSecondaryContainer">@color/md_theme_onSecondaryContainer</item>
|
||||
<item name="colorTertiary">@color/md_theme_tertiary</item>
|
||||
<item name="colorOnTertiary">@color/md_theme_onTertiary</item>
|
||||
<item name="colorTertiaryContainer">@color/md_theme_tertiaryContainer</item>
|
||||
<item name="colorOnTertiaryContainer">@color/md_theme_onTertiaryContainer</item>
|
||||
<item name="colorError">@color/md_theme_error</item>
|
||||
<item name="colorOnError">@color/md_theme_onError</item>
|
||||
<item name="colorErrorContainer">@color/md_theme_errorContainer</item>
|
||||
<item name="colorOnErrorContainer">@color/md_theme_onErrorContainer</item>
|
||||
<item name="android:colorBackground">@color/md_theme_background</item>
|
||||
<item name="colorOnBackground">@color/md_theme_onBackground</item>
|
||||
<item name="colorSurface">@color/md_theme_surface</item>
|
||||
@@ -26,11 +17,68 @@
|
||||
<item name="colorOnSurfaceVariant">@color/md_theme_onSurfaceVariant</item>
|
||||
<item name="colorOutline">@color/md_theme_outline</item>
|
||||
<item name="colorOutlineVariant">@color/md_theme_outlineVariant</item>
|
||||
<item name="colorSurfaceInverse">@color/md_theme_inverseSurface</item>
|
||||
<item name="colorOnSurfaceInverse">@color/md_theme_inverseOnSurface</item>
|
||||
<item name="colorPrimaryInverse">@color/md_theme_inversePrimary</item>
|
||||
|
||||
<!-- 窗口背景透明(适配 BottomAppBar) -->
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<!-- Typecho 风格二级导航 -->
|
||||
<style name="Widget.Lvnote.TabLayout.Secondary" parent="Widget.Material3.TabLayout">
|
||||
<item name="tabIndicatorColor">?colorPrimary</item>
|
||||
<item name="tabIndicatorHeight">2dp</item>
|
||||
<item name="tabIndicatorFullWidth">false</item>
|
||||
<item name="tabIndicatorAnimationMode">elastic</item>
|
||||
<item name="tabPaddingStart">16dp</item>
|
||||
<item name="tabPaddingEnd">16dp</item>
|
||||
<item name="tabTextAppearance">@style/TextAppearance.Lvnote.Tab.Secondary</item>
|
||||
<item name="tabSelectedTextColor">?colorPrimary</item>
|
||||
<item name="tabMode">fixed</item>
|
||||
<item name="tabGravity">fill</item>
|
||||
<item name="android:background">?android:attr/colorBackground</item>
|
||||
<item name="android:elevation">0dp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Lvnote.Tab.Secondary" parent="TextAppearance.Material3.LabelLarge">
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
<item name="android:letterSpacing">0.02</item>
|
||||
</style>
|
||||
<!-- 在 <resources> 内添加 -->
|
||||
<style name="Widget.Lvnote.SegmentedButton" parent="Widget.Material3.Button.OutlinedButton">
|
||||
<item name="android:minWidth">60dp</item>
|
||||
<item name="android:minHeight">36dp</item>
|
||||
<item name="android:insetTop">0dp</item>
|
||||
<item name="android:insetBottom">0dp</item>
|
||||
<item name="android:paddingStart">16dp</item>
|
||||
<item name="android:paddingEnd">16dp</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:textStyle">normal</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
<item name="android:textColor">@color/segmented_button_text</item>
|
||||
<item name="backgroundTint">@color/segmented_button_bg</item>
|
||||
<item name="strokeColor">?attr/colorPrimary</item>
|
||||
<item name="strokeWidth">1dp</item>
|
||||
<item name="cornerRadius">18dp</item>
|
||||
</style>
|
||||
<!-- 未选中:14sp 灰色 -->
|
||||
<style name="TextAppearance.Lvnote.Tab.Unselected" parent="TextAppearance.Material3.LabelLarge">
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:textColor">#9E9E9E</item>
|
||||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
</style>
|
||||
|
||||
<!-- 选中:20sp 加粗主色 -->
|
||||
<style name="TextAppearance.Lvnote.Tab.Selected" parent="TextAppearance.Material3.TitleMedium">
|
||||
<item name="android:textSize">20sp</item>
|
||||
<item name="android:textColor">?colorPrimary</item>
|
||||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
<item name="android:textStyle">bold</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
</style>
|
||||
|
||||
<!-- 按钮背景选择器 -->
|
||||
<color name="segmented_button_checked">#4157FF</color> <!-- 主色填充 -->
|
||||
<color name="segmented_button_unchecked">@android:color/transparent</color>
|
||||
|
||||
</resources>
|
||||
Reference in New Issue
Block a user