This commit is contained in:
lihongwei 2024-09-18 15:10:59 +08:00
parent 0b7ec644cd
commit 558cf6d98d
24 changed files with 828 additions and 2 deletions

View File

@ -40,6 +40,7 @@ dependencies {
implementation("androidx.appcompat:appcompat:1.7.0")
implementation("com.google.android.material:material:1.12.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.activity:activity:1.9.1")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")

View File

@ -2,7 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
@ -13,9 +14,11 @@
android:supportsRtl="true"
android:theme="@style/Theme.MusicApp"
tools:targetApi="31">
<activity
android:name=".ui.MainActivity"
android:exported="false" />
<activity
android:name=".ui.HomeActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@ -0,0 +1,36 @@
package com.hi.music.player.adapter;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import com.hi.music.player.ui.HomeFragment;
import com.hi.music.player.ui.ProfileFragment;
import com.hi.music.player.ui.SearchFragment;
import java.util.ArrayList;
import java.util.List;
public class HomeViewPagerAdapter extends FragmentStateAdapter {
private final List<Fragment> fragments = new ArrayList<>();
public HomeViewPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
fragments.add(new HomeFragment());
fragments.add(new SearchFragment());
fragments.add(new ProfileFragment());
}
@NonNull
@Override
public Fragment createFragment(int position) {
return fragments.get(position);
}
@Override
public int getItemCount() {
return fragments.size();
}
}

View File

@ -0,0 +1,93 @@
package com.hi.music.player.ui;
import android.os.Bundle;
import android.view.LayoutInflater;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.hi.music.player.R;
import com.hi.music.player.adapter.HomeViewPagerAdapter;
import com.hi.music.player.databinding.ActivityHomeBinding;
import com.hi.music.player.databinding.HomeTabCustomBinding;
public class HomeActivity extends BaseActivity<ActivityHomeBinding> {
// 图标数组定义为类成员避免重复
private final int[] defaultIcons = {
R.drawable.home_unselect,
R.drawable.search_unselect,
R.drawable.profile_unselect
};
private final int[] selectedIcons = {
R.drawable.home_select,
R.drawable.search_select,
R.drawable.profile_select
};
@Override
protected ActivityHomeBinding getViewBinding() {
return ActivityHomeBinding.inflate(getLayoutInflater());
}
@Override
protected void onCreateInit() {
initView(); // 可以在这里初始化视图
}
@Override
public boolean isFullScreen() {
return false;
}
@Override
public boolean statusBarLight() {
return false;
}
public void initView() {
HomeViewPagerAdapter adapter = new HomeViewPagerAdapter(this);
vb.homeViewPager.setAdapter(adapter);
// 设置TabLayout的图标
new TabLayoutMediator(vb.homeTabLayout, vb.homeViewPager, (tab, position) -> {
HomeTabCustomBinding tabBinding = HomeTabCustomBinding.inflate(LayoutInflater.from(this));
tab.setCustomView(tabBinding.getRoot());
tabBinding.homeIcon.setImageResource(defaultIcons[position]); // 默认图标
}).attach();
// 添加Tab选中与未选中事件监听器
vb.homeTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
updateTabIcon(tab, true); // 更新选中的图标
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
updateTabIcon(tab, false); // 恢复未选中图标
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
// 可选重复选择Tab时的操作
}
});
// 设置默认选中第一个
TabLayout.Tab firstTab = vb.homeTabLayout.getTabAt(0);
if (firstTab != null) {
firstTab.select();
updateTabIcon(firstTab, true); // 设置选中的图标
}
}
private void updateTabIcon(TabLayout.Tab tab, boolean isSelected) {
HomeTabCustomBinding tabBinding = HomeTabCustomBinding.bind(tab.getCustomView());
int position = tab.getPosition();
tabBinding.homeIcon.setImageResource(isSelected ? selectedIcons[position] : defaultIcons[position]);
}
}

View File

@ -0,0 +1,22 @@
package com.hi.music.player.ui;
import com.hi.music.player.R;
import com.hi.music.player.databinding.FragmentHomeBinding;
public class HomeFragment extends BaseFragment<FragmentHomeBinding> {
@Override
protected FragmentHomeBinding getFragmentVb() {
// 返回正确的 ViewBinding 实例
return FragmentHomeBinding.inflate(getLayoutInflater());
}
@Override
protected void initView() {
// 在这里进行视图的初始化操作
//标题导航栏颜色设置
Vb.toolbar.setTitleTextColor(getResources().getColor(R.color.white));
}
}

View File

@ -0,0 +1,27 @@
package com.hi.music.player.ui;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.hi.music.player.R;
import com.hi.music.player.databinding.FragmentProfileBinding;
public class ProfileFragment extends BaseFragment<FragmentProfileBinding> {
@Override
protected FragmentProfileBinding getFragmentVb() {
return FragmentProfileBinding.inflate(getLayoutInflater());
}
@Override
protected void initView() {
}
}

View File

@ -0,0 +1,27 @@
package com.hi.music.player.ui;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.hi.music.player.R;
import com.hi.music.player.databinding.FragmentSearchBinding;
public class SearchFragment extends BaseFragment<FragmentSearchBinding> {
@Override
protected FragmentSearchBinding getFragmentVb() {
return FragmentSearchBinding.inflate(getLayoutInflater());
}
@Override
protected void initView() {
}
}

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 渐变背景层 -->
<item>
<shape android:shape="rectangle">
<!-- 渐变效果 -->
<gradient
android:angle="90"
android:endColor="#121212"
android:startColor="#59033A07" />
</shape>
</item>
</selector>

View File

@ -0,0 +1,19 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:strokeWidth="1"
android:pathData="M18,18m-17.5,0a17.5,17.5 0,1 1,35 0a17.5,17.5 0,1 1,-35 0"
android:fillColor="#00000000"
android:strokeColor="#80F988"/>
<group>
<clip-path
android:pathData="M4,4h28v28h-28z"/>
<path
android:pathData="M18,25.875C18.478,25.875 18.875,25.478 18.875,25V21.499C18.875,21.021 18.478,20.624 18,20.624C17.522,20.624 17.125,21.021 17.125,21.499V25C17.125,25.478 17.522,25.875 18,25.875ZM8.41,11.966C7.243,12.876 6.322,14.743 6.322,16.213V24.264C6.322,27.24 8.737,29.667 11.712,29.667H24.288C27.263,29.667 29.678,27.251 29.678,24.276V16.365C29.678,14.79 28.663,12.853 27.38,11.955L20.66,7.252C18.828,5.969 16.017,6.039 14.255,7.404L8.41,11.966Z"
android:fillColor="#80F988"
android:fillType="evenOdd"/>
</group>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="28"
android:viewportHeight="28">
<path
android:pathData="M14,21.875C14.478,21.875 14.875,21.478 14.875,21V17.499C14.875,17.021 14.478,16.624 14,16.624C13.522,16.624 13.125,17.021 13.125,17.499V21C13.125,21.478 13.522,21.875 14,21.875ZM4.41,7.966C3.243,8.876 2.322,10.743 2.322,12.213V20.264C2.322,23.24 4.737,25.667 7.712,25.667H20.288C23.263,25.667 25.678,23.251 25.678,20.276V12.365C25.678,10.79 24.663,8.853 23.38,7.955L16.66,3.252C14.828,1.969 12.017,2.039 10.255,3.404L4.41,7.966Z"
android:fillColor="#ffffff"
android:fillAlpha="0.6"
android:fillType="evenOdd"/>
</vector>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M7.283,5H20M20,12H4M20,19H12.972"
android:strokeWidth="1.5"
android:fillColor="#00000000"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:strokeWidth="1"
android:pathData="M18,18m-17.5,0a17.5,17.5 0,1 1,35 0a17.5,17.5 0,1 1,-35 0"
android:fillColor="#00000000"
android:strokeColor="#80F988"/>
<path
android:pathData="M22.445,22.593C24.09,21.548 25.351,19.998 26.039,18.176C26.728,16.354 26.806,14.357 26.262,12.486C25.719,10.615 24.582,8.972 23.024,7.802C21.466,6.632 19.571,6 17.623,6C15.675,6 13.779,6.632 12.221,7.802C10.663,8.972 9.527,10.615 8.983,12.486C8.44,14.357 8.518,16.354 9.206,18.176C9.894,19.998 11.156,21.548 12.8,22.593C11.519,23.199 10.419,24.131 9.612,25.297C8.804,26.462 8.317,27.819 8.2,29.232C8.195,29.43 8.269,29.622 8.405,29.766C8.541,29.91 8.728,29.994 8.926,30H26.362C26.46,29.998 26.557,29.976 26.647,29.936C26.738,29.896 26.819,29.839 26.887,29.768C26.955,29.696 27.008,29.612 27.044,29.521C27.079,29.429 27.096,29.331 27.094,29.232C26.973,27.814 26.479,26.453 25.663,25.287C24.847,24.121 23.737,23.191 22.445,22.593ZM21.749,19.132C21.231,19.715 20.601,20.189 19.896,20.525C19.192,20.861 18.427,21.052 17.647,21.087H17.443C15.913,20.956 14.492,20.243 13.472,19.096C13.405,19.019 13.354,18.929 13.322,18.833C13.29,18.736 13.277,18.633 13.285,18.532C13.294,18.43 13.322,18.331 13.369,18.24C13.416,18.15 13.48,18.069 13.559,18.004C13.637,17.939 13.728,17.89 13.826,17.86C13.923,17.831 14.026,17.821 14.127,17.832C14.229,17.842 14.327,17.873 14.417,17.922C14.506,17.971 14.585,18.038 14.648,18.118C15.403,18.949 16.439,19.471 17.557,19.581C18.631,19.635 19.704,19.114 20.748,18.076C20.889,17.942 21.077,17.869 21.271,17.872C21.466,17.875 21.651,17.953 21.789,18.091C21.926,18.228 22.005,18.414 22.007,18.608C22.01,18.802 21.937,18.99 21.803,19.132H21.749Z"
android:fillColor="#80F988"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="28"
android:viewportHeight="28">
<path
android:pathData="M18.445,18.593C20.09,17.548 21.351,15.998 22.039,14.176C22.728,12.354 22.806,10.357 22.262,8.486C21.719,6.615 20.582,4.972 19.024,3.802C17.466,2.632 15.571,2 13.623,2C11.675,2 9.779,2.632 8.221,3.802C6.663,4.972 5.527,6.615 4.983,8.486C4.44,10.357 4.518,12.354 5.206,14.176C5.894,15.998 7.156,17.548 8.8,18.593C7.519,19.199 6.419,20.131 5.612,21.297C4.804,22.462 4.317,23.819 4.2,25.232C4.195,25.43 4.269,25.622 4.405,25.766C4.541,25.91 4.728,25.994 4.926,26H22.362C22.46,25.998 22.557,25.976 22.647,25.936C22.738,25.896 22.819,25.839 22.887,25.768C22.955,25.696 23.008,25.612 23.044,25.521C23.079,25.429 23.096,25.331 23.094,25.232C22.973,23.814 22.479,22.453 21.663,21.287C20.847,20.121 19.737,19.191 18.445,18.593ZM17.749,15.132C17.231,15.715 16.601,16.189 15.896,16.525C15.192,16.861 14.427,17.052 13.647,17.087H13.443C11.913,16.956 10.492,16.243 9.472,15.096C9.405,15.019 9.354,14.929 9.322,14.833C9.29,14.736 9.277,14.633 9.286,14.532C9.294,14.43 9.322,14.331 9.369,14.24C9.416,14.15 9.48,14.069 9.559,14.004C9.637,13.939 9.728,13.89 9.826,13.86C9.923,13.831 10.026,13.821 10.127,13.832C10.229,13.842 10.327,13.873 10.417,13.922C10.506,13.971 10.585,14.038 10.648,14.118C11.403,14.949 12.439,15.471 13.557,15.582C14.63,15.635 15.704,15.114 16.748,14.076C16.889,13.942 17.077,13.869 17.271,13.872C17.466,13.875 17.651,13.953 17.789,14.091C17.926,14.228 18.005,14.414 18.007,14.608C18.01,14.802 17.937,14.99 17.803,15.132H17.749Z"
android:fillColor="#ffffff"
android:fillAlpha="0.6"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M8.97,17.53C8.677,17.237 8.677,16.763 8.97,16.47L13.439,12L8.97,7.53C8.677,7.237 8.677,6.763 8.97,6.47C9.263,6.177 9.737,6.177 10.03,6.47L15.03,11.47C15.171,11.61 15.25,11.801 15.25,12C15.25,12.199 15.171,12.39 15.03,12.53L10.03,17.53C9.737,17.823 9.263,17.823 8.97,17.53Z"
android:fillColor="#ffffff"
android:fillAlpha="0.85"
android:fillType="evenOdd"/>
</vector>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<!-- 合并四个圆角为一个通用半径 -->
<corners android:radius="24dp" />
</shape>
</item>
</selector>

View File

@ -0,0 +1,36 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 渐变背景层 -->
<item>
<shape android:shape="rectangle">
<!-- 只设置顶部的圆角 -->
<corners
android:topLeftRadius="24dp"
android:topRightRadius="24dp"
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp" />
<!-- 渐变效果 -->
<gradient
android:angle="90"
android:endColor="#0080EF88"
android:startColor="#8080EF88" />
</shape>
</item>
<!-- 半透明覆盖层 -->
<item>
<shape android:shape="rectangle">
<!-- 同样只设置顶部的圆角 -->
<corners
android:topLeftRadius="24dp"
android:topRightRadius="24dp"
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp" />
<!-- 半透明的颜色覆盖层 -->
<solid android:color="#26FFFFFF" />
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,22 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:strokeWidth="1"
android:pathData="M18,18m-17.5,0a17.5,17.5 0,1 1,35 0a17.5,17.5 0,1 1,-35 0"
android:fillColor="#00000000"
android:strokeColor="#80F988"/>
<group>
<clip-path
android:pathData="M32,4l-28,0l-0,28l28,0z"/>
<path
android:pathData="M17.5,6C11.149,6 6,11.149 6,17.5C6,23.851 11.149,29 17.5,29C23.851,29 29,23.851 29,17.5C29,11.149 23.851,6 17.5,6ZM15.354,10.861C15.819,10.795 16.176,10.395 16.176,9.912C16.176,9.383 15.747,8.954 15.218,8.954C15.16,8.954 15.104,8.959 15.049,8.968C11.923,9.472 9.472,11.923 8.968,15.049C8.959,15.104 8.954,15.16 8.954,15.218C8.954,15.747 9.383,16.176 9.912,16.176C10.395,16.176 10.795,15.819 10.861,15.354C11.233,13.044 13.044,11.233 15.354,10.861Z"
android:fillColor="#80F988"
android:fillType="evenOdd"/>
<path
android:pathData="M29.431,29.434C29.745,29.107 29.745,28.594 29.431,28.279L27.264,26.111C26.938,25.796 26.425,25.796 26.111,26.111C25.796,26.437 25.796,26.95 26.111,27.265L28.278,29.434C28.429,29.585 28.639,29.667 28.848,29.667C29.058,29.667 29.268,29.585 29.431,29.434Z"
android:fillColor="#80F988"/>
</group>
</vector>

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="28"
android:viewportHeight="28">
<path
android:pathData="M13.5,2C7.149,2 2,7.149 2,13.5C2,19.851 7.149,25 13.5,25C19.851,25 25,19.851 25,13.5C25,7.149 19.851,2 13.5,2ZM11.354,6.861C11.819,6.795 12.176,6.395 12.176,5.912C12.176,5.383 11.747,4.954 11.218,4.954C11.16,4.954 11.104,4.959 11.049,4.968C7.923,5.472 5.472,7.923 4.968,11.049C4.959,11.104 4.954,11.16 4.954,11.218C4.954,11.747 5.383,12.176 5.912,12.176C6.395,12.176 6.795,11.819 6.861,11.354C7.233,9.044 9.044,7.233 11.354,6.861Z"
android:fillColor="#ffffff"
android:fillAlpha="0.6"
android:fillType="evenOdd"/>
<path
android:pathData="M25.431,25.434C25.745,25.107 25.745,24.594 25.431,24.279L23.264,22.111C22.938,21.796 22.425,21.796 22.111,22.111C21.796,22.437 21.796,22.95 22.111,23.265L24.278,25.434C24.429,25.585 24.639,25.667 24.848,25.667C25.058,25.667 25.268,25.585 25.431,25.434Z"
android:fillColor="#ffffff"
android:fillAlpha="0.6"/>
</vector>

View File

@ -0,0 +1,24 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/home_background"
tools:context=".ui.HomeActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/home_view_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/home_tab_layout"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/home_tab_layout"
android:layout_width="match_parent"
android:layout_height="72dp"
app:tabRippleColor="@android:color/transparent"
app:tabIndicatorHeight="0dp"
android:background="@drawable/rounded_rectangle_tab_layout"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,204 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.HomeFragment">
<!-- 顶部应用栏 -->
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="@string/musicoo" />
</com.google.android.material.appbar.AppBarLayout>
<!-- 滚动视图 -->
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- Song Of The Day -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<TextView
android:id="@+id/tv_song_of_the_day"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/song_of_the_day"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/iv_song_of_the_day"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/right_arrow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_song_of_the_day"
android:layout_marginEnd="8dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_song_of_the_day"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
<!-- Recently Played -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<TextView
android:id="@+id/tv_recently_played"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/recently_played"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/iv_recently_played"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/right_arrow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_recently_played"
android:layout_marginEnd="8dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_recently_played"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
<!-- Top Artists -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<TextView
android:id="@+id/tv_top_artists"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/top_artists"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/iv_top_artists"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/right_arrow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_top_artists"
android:layout_marginEnd="8dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_top_artists"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
<!-- Trending in Shorts -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<TextView
android:id="@+id/tv_trending_shorts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/trending_in_shorts"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/iv_trending_shorts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/right_arrow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_trending_shorts"
android:layout_marginEnd="8dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_trending_shorts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
<!-- New Releases -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp">
<TextView
android:id="@+id/tv_new_releases"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/new_releases"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/iv_new_releases"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/right_arrow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_new_releases"
android:layout_marginEnd="8dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_new_releases"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,179 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1e2b28"
tools:context=".ui.ProfileFragment">
<!-- 第一行: 左边文字,右边控件 -->
<TextView
android:id="@+id/titleText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="16dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/library"
android:textColor="#ffffff"
android:textSize="24sp"
app:layout_constraintEnd_toStartOf="@id/settingsIcon"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/settingsIcon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_margin="16dp"
android:src="@drawable/ic_launcher_background"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- 第二行: 左边和右边矩形区域, 中央图标+两行文字 -->
<LinearLayout
android:id="@+id/leftSection"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintEnd_toStartOf="@id/rightSection"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/titleText">
<!-- 矩形背景 -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_gravity="center"
android:background="@drawable/round_rectangle"
android:backgroundTint="@android:color/holo_green_light">
<!-- 中央图标 -->
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:src="@drawable/ic_launcher_foreground" />
</FrameLayout>
<!-- 标题 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="Title 1"
android:textColor="#ffffff"
android:textSize="16sp" />
<!-- 副标题 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="Subtitle"
android:textColor="#ffffff"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/rightSection"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/leftSection"
app:layout_constraintTop_toBottomOf="@id/titleText">
<!-- 矩形背景和中央图标 -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_gravity="center"
android:background="@drawable/round_rectangle"
android:backgroundTint="@android:color/holo_red_light">
<!-- 中央图标 -->
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:src="@drawable/ic_launcher_foreground" />
</FrameLayout>
<!-- 标题 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="Title 2"
android:textColor="#ffffff"
android:textSize="16sp" />
<!-- 副标题 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="Subtitle"
android:textColor="#ffffff"
android:textSize="12sp" />
</LinearLayout>
<!-- 第三行: 一行文字 -->
<TextView
android:id="@+id/singleTextRow"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="left"
android:padding="16dp"
android:text="This is a single text row"
android:textColor="#ffffff"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/rightSection" />
<!-- 第四行: 左边控件,右边文字 -->
<ImageView
android:id="@+id/iconLeft"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_margin="16dp"
android:src="@drawable/ic_launcher_background"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/singleTextRow" />
<TextView
android:id="@+id/rightText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:padding="16dp"
android:text="This is right-aligned text"
android:textColor="#ffffff"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/iconLeft"
app:layout_constraintTop_toBottomOf="@id/singleTextRow" />
<!-- 第五行: RecyclerView -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
android:padding="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iconLeft" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.SearchFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/home_icon"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,3 +1,12 @@
<resources>
<string name="app_name">MusicApp</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
<string name="song_of_the_day">Song Of The Day</string>
<string name="recently_played">Recently Played</string>
<string name="top_artists">Top Artists</string>
<string name="trending_in_shorts">Trending in Shorts</string>
<string name="new_releases">New Releases</string>
<string name="musicoo">Musicoo</string>
<string name="library">Profile</string>
</resources>