app/src/main/AndroidManifest.xml
@@ -83,7 +83,13 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.FirstApp" tools:targetApi="31"> tools:targetApi="31" android:usesCleartextTraffic="true" > <activity android:name=".activity.VipActivity" android:exported="false" android:theme="@style/Theme.FirstApp" /> <activity android:name=".ui.reminderOther.ReminderOtherAddActivity2" android:configChanges="orientation|keyboardHidden|screenSize" @@ -106,14 +112,14 @@ android:exported="false" /> <activity android:name=".activity.PickupActivity" android:exported="false"/> <activity android:name=".activity.ContentDetailActivity" android:theme="@style/Theme.ContentDetail" android:exported="false" /> <activity android:name=".activity.ContentDetailActivity" android:exported="false" android:theme="@style/Theme.ContentDetail" /> <activity android:name=".ui.profile.EditProfileActivity" android:exported="false"/> android:exported="false" /> </application> </manifest> app/src/main/java/com/example/firstapp/activity/FirstFragment.kt
对比新文件 @@ -0,0 +1,45 @@ package com.example.firstapp.activity import android.os.Bundle import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.navigation.fragment.findNavController import com.example.firstapp.R import com.example.firstapp.databinding.FragmentFirstBinding /** * A simple [Fragment] subclass as the default destination in the navigation. */ class FirstFragment : Fragment() { private var _binding: FragmentFirstBinding? = null // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentFirstBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.buttonFirst.setOnClickListener { findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment) } } override fun onDestroyView() { super.onDestroyView() _binding = null } } app/src/main/java/com/example/firstapp/activity/SecondFragment.kt
对比新文件 @@ -0,0 +1,45 @@ package com.example.firstapp.activity import android.os.Bundle import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.navigation.fragment.findNavController import com.example.firstapp.R import com.example.firstapp.databinding.FragmentSecondBinding /** * A simple [Fragment] subclass as the second destination in the navigation. */ class SecondFragment : Fragment() { private var _binding: FragmentSecondBinding? = null // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentSecondBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.buttonSecond.setOnClickListener { findNavController().navigate(R.id.action_SecondFragment_to_FirstFragment) } } override fun onDestroyView() { super.onDestroyView() _binding = null } } app/src/main/java/com/example/firstapp/activity/VipActivity.kt
对比新文件 @@ -0,0 +1,108 @@ package com.example.firstapp.activity import android.graphics.Color import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.cardview.widget.CardView import androidx.core.content.ContextCompat import androidx.navigation.ui.AppBarConfiguration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.example.firstapp.R import com.example.firstapp.adapter.CardAdapter import com.example.firstapp.databinding.ActivityVipBinding import com.example.firstapp.entity.CardData import com.example.firstapp.utils.Log class VipActivity : AppCompatActivity() { private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var binding: ActivityVipBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityVipBinding.inflate(layoutInflater) setContentView(binding.root) setSupportActionBar(binding.toolbar) // 显式设置 MaterialToolbar 的标题 supportActionBar?.title = "" // 如果不需要 ActionBar 的导航功能,可以禁用 // supportActionBar?.setDisplayHomeAsUpEnabled(false) // supportActionBar?.setDisplayShowHomeEnabled(false) // 返回事件 binding.ivBack.setOnClickListener{ finish() } val recyclerView = findViewById<RecyclerView>(R.id.recycler_view) recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false) val cardList = listOf( CardData.ContinueMonthly( "首月限时特惠", "连续包月", "首次开通", "¥9.9", "次月起12元/月", "自动续费可随时取消" ), CardData.Yearly( "折合9元/月", "年卡", "¥108/年", "¥168" ), CardData.SingleMonth( "1个月", "¥15" ) ) val adapter = CardAdapter(cardList) {cardViewList, cardData, cardView -> handleCardClick(cardViewList,cardData,cardView) } recyclerView.adapter = adapter try { val firstMonthCardView = findViewById<CardView>(R.id.vip_first_month_card_view) firstMonthCardView.foreground = ContextCompat.getDrawable(this, R.drawable.gray_border_shape) // 设置自定义背景 }catch (e: Exception){ e.stackTrace Log.e("VipActivity",e.message+"") } } /** * 会员卡样式点击事件 */ private fun handleCardClick(cardViewList: MutableList<CardView>,cardData: CardData, cardView: CardView) { // 处理点击事件,修改样式 // 修改所有的边框色都是灰色 cardViewList.forEach { card -> card.foreground = ContextCompat.getDrawable(this, R.drawable.gray_border_shape) // 设置自定义背景 } // 单独将点击的卡片边框颜色改为金色 // cardView.setCardBackgroundColor(Color.parseColor("#FF0000")) // 举例:设置背景颜色 cardView.foreground = ContextCompat.getDrawable(this, R.drawable.gold_border_shape) // 设置自定义背景 val title = when (cardData) { is CardData.ContinueMonthly -> cardData.title is CardData.Yearly -> cardData.title is CardData.SingleMonth -> cardData.title } // 处理点击事件,这里我们只是简单地展示一个 Toast Toast.makeText(this, "点击了: ${title}", Toast.LENGTH_SHORT).show() } } app/src/main/java/com/example/firstapp/adapter/CardAdapter.kt
对比新文件 @@ -0,0 +1,126 @@ package com.example.firstapp.adapter import android.graphics.Color import android.graphics.Paint import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.cardview.widget.CardView import androidx.recyclerview.widget.RecyclerView import com.example.firstapp.R import com.example.firstapp.entity.CardData class CardAdapter(private val cardList: List<CardData>, private val itemClickListener: (MutableList<CardView>, CardData, CardView) -> Unit ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { private val CONTINUE_MONTHLY_VIEW_TYPE = 0 private val YEARLY_VIEW_TYPE = 1 private val SINGLE_MONTH_VIEW_TYPE = 2 private val cardViewList: MutableList<CardView> = mutableListOf() override fun getItemViewType(position: Int): Int { return when (cardList[position]) { is CardData.ContinueMonthly -> CONTINUE_MONTHLY_VIEW_TYPE is CardData.Yearly -> YEARLY_VIEW_TYPE is CardData.SingleMonth -> SINGLE_MONTH_VIEW_TYPE } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return when (viewType) { CONTINUE_MONTHLY_VIEW_TYPE -> { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_card_continue_monthly, parent, false) ContinueMonthlyViewHolder(view) } YEARLY_VIEW_TYPE -> { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_card_yearly, parent, false) YearlyViewHolder(view) } SINGLE_MONTH_VIEW_TYPE -> { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_card_single_month, parent, false) SingleMonthViewHolder(view) } else -> throw IllegalArgumentException("Unknown view type") } } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { when (holder) { is ContinueMonthlyViewHolder -> { val data = cardList[position] as CardData.ContinueMonthly holder.firstMonthTag.text = data.firstMonthTag holder.titleText.text = data.title holder.subTitleText.text = data.subTitle holder.priceText.text = data.price holder.nextPriceText.text = data.nextPrice holder.autoRenewText.text = data.autoRenew cardViewList.add(holder.cardView) holder.itemView.setOnClickListener { itemClickListener(cardViewList,data, holder.cardView) } // 设置点击事件 } is YearlyViewHolder -> { val data = cardList[position] as CardData.Yearly holder.discountTag.text = data.discountTag holder.titleText.text = data.title holder.priceText.text = data.price holder.originalPriceText.text = data.originalPrice // 设置中划线 val paint = holder.originalPriceText.paint paint.flags = paint.flags or Paint.STRIKE_THRU_TEXT_FLAG paint.color = Color.RED // 设置中划线的颜色 cardViewList.add(holder.cardView) holder.itemView.setOnClickListener { itemClickListener(cardViewList,data, holder.cardView) } // 设置点击事件 } is SingleMonthViewHolder -> { val data = cardList[position] as CardData.SingleMonth holder.titleText.text = data.title holder.priceText.text = data.price cardViewList.add(holder.cardView) holder.itemView.setOnClickListener { itemClickListener(cardViewList,data, holder.cardView) } // 设置点击事件 } } } override fun getItemCount(): Int { return cardList.size } inner class ContinueMonthlyViewHolder(view: View) : RecyclerView.ViewHolder(view) { val cardView: CardView = view.findViewById(R.id.vip_first_month_card_view) val firstMonthTag: TextView = view.findViewById(R.id.first_month_tag) val titleText: TextView = view.findViewById(R.id.title_text) val subTitleText: TextView = view.findViewById(R.id.sub_title_text) val priceText: TextView = view.findViewById(R.id.price_text) val nextPriceText: TextView = view.findViewById(R.id.next_price_text) val autoRenewText: TextView = view.findViewById(R.id.auto_renew_text) } inner class YearlyViewHolder(view: View) : RecyclerView.ViewHolder(view) { val cardView: CardView = view.findViewById(R.id.vip_year_card_view) val discountTag: TextView = view.findViewById(R.id.discount_tag) val titleText: TextView = view.findViewById(R.id.yearly_title_text) val priceText: TextView = view.findViewById(R.id.yearly_price_text) val originalPriceText: TextView = view.findViewById(R.id.yearly_original_price_text) } inner class SingleMonthViewHolder(view: View) : RecyclerView.ViewHolder(view) { val cardView: CardView = view.findViewById(R.id.vip_month_card_view) val titleText: TextView = view.findViewById(R.id.single_month_title_text) val priceText: TextView = view.findViewById(R.id.single_month_price_text) } } app/src/main/java/com/example/firstapp/entity/CardData.kt
对比新文件 @@ -0,0 +1,24 @@ package com.example.firstapp.entity sealed class CardData { data class ContinueMonthly( val firstMonthTag: String, val title: String, val subTitle: String, val price: String, val nextPrice: String, val autoRenew: String ) : CardData() data class Yearly( val discountTag: String, val title: String, val price: String, val originalPrice: String ) : CardData() data class SingleMonth( val title: String, val price: String ) : CardData() } app/src/main/java/com/example/firstapp/ui/notifications/NotificationsFragment.kt
@@ -31,6 +31,7 @@ import com.google.android.material.snackbar.Snackbar import kotlinx.coroutines.launch import com.bumptech.glide.Glide import com.example.firstapp.activity.VipActivity import com.example.firstapp.database.response.UserInfo class NotificationsFragment : Fragment() { @@ -232,7 +233,10 @@ // VIP续费 binding.btnRenew.setOnClickListener { Toast.makeText(context, "VIP续费功能开发中", Toast.LENGTH_SHORT).show() // Toast.makeText(context, "VIP续费功能开发中", Toast.LENGTH_SHORT).show() // 跳转到vipActivity val intent = Intent(requireContext(), VipActivity::class.java) startActivity(intent) } } app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardFragment.kt
对比新文件 @@ -0,0 +1,118 @@ package com.example.firstapp.ui.vip import android.graphics.drawable.Drawable import androidx.fragment.app.viewModels import android.os.Bundle import android.util.Log import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView import androidx.databinding.DataBindingUtil import com.bumptech.glide.Glide import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.target.Target import com.bumptech.glide.load.DataSource import com.example.firstapp.R import com.example.firstapp.databinding.FragmentMemberInfoCardBinding class MemberInfoCardFragment : Fragment() { companion object { fun newInstance() = MemberInfoCardFragment() } private val viewModel: MemberInfoCardViewModel by viewModels() // 绑定变量 private var _binding: FragmentMemberInfoCardBinding? = null private val binding get() = _binding!! override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { // 使用 DataBindingUtil.inflate 来绑定布局 _binding = FragmentMemberInfoCardBinding.inflate(inflater, container, false) binding.viewModel = viewModel binding.lifecycleOwner = this // 绑定头像 Glide.with(this) .load("http://192.168.1.201:9000/sms/avatar/avatar.jpg") .transform(RoundedCorners(100)) // 设置圆角 .error(R.drawable.error_placeholder) // 如果加载失败,显示占位图 .listener(object : RequestListener<Drawable> { override fun onResourceReady( resource: Drawable?, model: Any?, target: Target<Drawable>?, // 正确使用 Target 作为泛型参数 dataSource: DataSource?, // 导入正确的 DataSource isFirstResource: Boolean ): Boolean { Log.d("Glide", "Image loaded successfully") return false } override fun onLoadFailed( e: GlideException?, model: Any?, target: Target<Drawable>?, // 正确使用 Target 作为泛型参数 isFirstResource: Boolean ): Boolean { Log.e("Glide", "Image load failed", e) return false } }) .into(binding.memberAvatarView) // 绑定会员徽章 Glide.with(this) .load("http://192.168.1.201:9000/sms/member/vip_no.png") .transform(RoundedCorners(100)) // 设置圆角 .error(R.drawable.error_placeholder) // 如果加载失败,显示占位图 .listener(object : RequestListener<Drawable> { override fun onResourceReady( resource: Drawable?, model: Any?, target: Target<Drawable>?, // 正确使用 Target 作为泛型参数 dataSource: DataSource?, // 导入正确的 DataSource isFirstResource: Boolean ): Boolean { Log.d("Glide", "Image loaded successfully") return false } override fun onLoadFailed( e: GlideException?, model: Any?, target: Target<Drawable>?, // 正确使用 Target 作为泛型参数 isFirstResource: Boolean ): Boolean { Log.e("Glide", "Image load failed", e) return false } }) .into(binding.memberImageView) return binding.root } override fun onDestroyView() { super.onDestroyView() _binding = null } } app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardViewModel.kt
对比新文件 @@ -0,0 +1,23 @@ package com.example.firstapp.ui.vip import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch class MemberInfoCardViewModel : ViewModel() { // TODO: Implement the ViewModel private val _phoneNumber = MutableStateFlow("18099999999") val phoneNumber: StateFlow<String> = _phoneNumber private val _memberStatus = MutableStateFlow("未开通") val memberStatus: StateFlow<String> = _memberStatus // 更新数据的方法 fun updatePhoneNumber(phoneNumber: String) { viewModelScope.launch { _phoneNumber.value = phoneNumber } } } app/src/main/res/drawable/error_placeholder.xml
对比新文件 @@ -0,0 +1,9 @@ <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="100dp" android:height="100dp" android:viewportWidth="24" android:viewportHeight="24"> <path android:fillColor="#FF6666" android:pathData="M12,2L2,22h20L12,2zM13,18h-2v-2h2v2zm0,-4h-2v-4h2v4z"/> </vector> app/src/main/res/drawable/gold_border_shape.xml
对比新文件 @@ -0,0 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@android:color/transparent"/> <!-- 背景透明 --> <stroke android:width="2dp" android:color="#F9EBC6"/> <!-- 金色边框 --> <corners android:radius="16dp"/> <!-- 圆角大小 --> </shape> app/src/main/res/drawable/gray_border_shape.xml
对比新文件 @@ -0,0 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@android:color/transparent"/> <!-- 背景透明 --> <stroke android:width="1dp" android:color="#FFFFFF"/> <!-- 金色边框 --> <corners android:radius="16dp"/> <!-- 圆角大小 --> </shape> app/src/main/res/drawable/ic_category.xml
对比新文件 @@ -0,0 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"> <path android:fillColor="#00BFFF" android:pathData="M10,6L8.59,7.41 13.17,12 8.59,16.59 10,18l6,-6z"/> </vector> app/src/main/res/drawable/ic_check.xml
对比新文件 @@ -0,0 +1,14 @@ <?xml version="1.0" encoding="utf-8"?> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"> <path android:fillColor="#FFFFFF" android:strokeWidth="2" android:strokeColor="#000000" android:pathData="M10.29,15.29 4,9 5.41,7.59 10.29,12.47 19.59,3.17 21,4.59 10.29,15.29"/> </vector> app/src/main/res/drawable/member_background.xml
对比新文件 @@ -0,0 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <gradient android:startColor="#000000" android:endColor="#7A7596" android:angle="90"/> </shape> app/src/main/res/drawable/round_red_bg.xml
对比新文件 @@ -0,0 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#FD6478"/> <!-- 设置背景颜色 --> <corners android:radius="100dp"/> <!-- 设置圆角半径 --> </shape> app/src/main/res/drawable/round_transition_gray_bg.xml
对比新文件 @@ -0,0 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 设置透明背景 --> <solid android:color="@android:color/transparent"/> <!-- 设置灰色边框 --> <stroke android:color="#808080" android:width="1dp"/> <!-- 可以调整宽度 --> <!-- 设置圆角 --> <corners android:radius="16dp"/> <!-- 设置圆角半径 --> </shape> app/src/main/res/layout/activity_vip.xml
对比新文件 @@ -0,0 +1,80 @@ <?xml version="1.0" encoding="utf-8"?> <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" android:fitsSystemWindows="true" android:background="@drawable/member_background" tools:context=".activity.VipActivity"> <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true" android:background="@android:color/transparent" > <com.google.android.material.appbar.MaterialToolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" > <!-- 直接在 Toolbar 中添加 TextView --> <ImageView android:id="@+id/ivBack" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left" android:layout_marginStart="16dp" android:src="@drawable/ic_back" /> <TextView android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="智信会员" android:textColor="#FFFFFF" android:textSize="18sp" android:layout_gravity="left" android:layout_marginEnd="16dp"/> </com.google.android.material.appbar.MaterialToolbar> </com.google.android.material.appbar.AppBarLayout> <!-- 引入 MemberInfoCardFragment --> <fragment android:name="com.example.firstapp.ui.vip.MemberInfoCardFragment" android:id="@+id/memberInfoCardFragment" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <!-- 滑动框--> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="200dp" android:layout_marginTop="200dp" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" android:background="@android:color/transparent" /> <!-- <include layout="@layout/content_vip" />--> <!-- <com.google.android.material.floatingactionbutton.FloatingActionButton--> <!-- android:id="@+id/fab"--> <!-- android:layout_width="wrap_content"--> <!-- android:layout_height="wrap_content"--> <!-- android:layout_gravity="bottom|end"--> <!-- android:layout_marginEnd="@dimen/fab_margin"--> <!-- android:layout_marginBottom="16dp"--> <!-- app:srcCompat="@android:drawable/ic_dialog_email" />--> </androidx.coordinatorlayout.widget.CoordinatorLayout> app/src/main/res/layout/content_vip.xml
对比新文件 @@ -0,0 +1,19 @@ <?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" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <fragment android:id="@+id/nav_host_fragment_content_vip" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="0dp" android:layout_height="0dp" app:defaultNavHost="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:navGraph="@navigation/nav_graph" /> </androidx.constraintlayout.widget.ConstraintLayout> app/src/main/res/layout/fragment_first.xml
对比新文件 @@ -0,0 +1,35 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.core.widget.NestedScrollView 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=".FirstFragment"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp"> <Button android:id="@+id/button_first" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/next" app:layout_constraintBottom_toTopOf="@id/textview_first" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/textview_first" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="@string/lorem_ipsum" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/button_first" /> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.core.widget.NestedScrollView> app/src/main/res/layout/fragment_member_info_card.xml
对比新文件 @@ -0,0 +1,81 @@ <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="viewModel" type="com.example.firstapp.ui.vip.MemberInfoCardViewModel"/> </data> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ui.vip.MemberInfoCardFragment"> <!-- CardView 内部的内容 --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="100dp" android:layout_marginTop="20dp" android:layout_marginLeft="15dp" android:layout_marginRight="15dp" app:cardCornerRadius="30dp" android:elevation="2dp"> <!-- 设置CardView的elevation --> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/memberCard" android:layout_width="match_parent" android:layout_height="80dp" android:layout_marginTop="10dp" tools:ignore="MissingConstraints"> <ImageView android:id="@+id/memberAvatarView" android:layout_width="60dp" android:layout_height="60dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:scaleType="centerCrop" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" /> <TextView android:id="@+id/phoneNumberText" android:layout_width="120dp" android:layout_height="60dp" android:gravity="center" android:text="@{viewModel.phoneNumber}" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toEndOf="@id/memberAvatarView" /> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="15dp" android:layout_marginTop="60dp" android:gravity="start" android:text="@{viewModel.memberStatus}" /> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.cardview.widget.CardView> <!-- 悬浮的 ImageView, 位于右侧 --> <ImageView android:id="@+id/memberImageView" android:layout_width="80dp" android:layout_height="80dp" android:layout_marginTop="0dp" android:layout_marginRight="40dp" android:scaleType="centerCrop" android:layout_gravity="end|top" android:elevation="4dp" /> <!-- 设置memberImageView的elevation,确保它在上层 --> </FrameLayout> </layout> app/src/main/res/layout/fragment_second.xml
对比新文件 @@ -0,0 +1,35 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.core.widget.NestedScrollView 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=".SecondFragment"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp"> <Button android:id="@+id/button_second" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/previous" app:layout_constraintBottom_toTopOf="@id/textview_second" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/textview_second" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="@string/lorem_ipsum" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/button_second" /> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.core.widget.NestedScrollView> app/src/main/res/layout/item_card.xml
对比新文件 @@ -0,0 +1,46 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="8dp" app:cardBackgroundColor="#F0F0F0" app:cardCornerRadius="16dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <TextView android:id="@+id/tag_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#FF0000" android:text="首月限时特惠" android:textColor="#FFFFFF" android:padding="16dp" /> <TextView android:id="@+id/title_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="连续包月" android:textSize="18sp" android:textColor="#333333" android:layout_marginTop="8dp" /> <TextView android:id="@+id/price_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="¥9.9" android:textSize="24sp" android:textColor="#FF0000" android:layout_marginTop="8dp" /> </LinearLayout> </androidx.cardview.widget.CardView> app/src/main/res/layout/item_card_continue_monthly.xml
对比新文件 @@ -0,0 +1,148 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="280dp" android:layout_height="wrap_content" android:layout_margin="8dp" android:background="@android:color/transparent" app:cardBackgroundColor="@android:color/transparent" app:cardElevation="0dp" app:cardUseCompatPadding="false" > <androidx.cardview.widget.CardView android:id="@+id/vip_first_month_card_view" 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="140dp" android:layout_marginTop="10dp" app:cardCornerRadius="16dp" android:foreground="@drawable/gold_border_shape" app:cardBackgroundColor="@android:color/transparent" app:cardElevation="0dp" app:cardUseCompatPadding="false"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" android:background="@android:color/transparent"> <!-- Title Text --> <TextView android:id="@+id/title_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="连续包月" android:textSize="18sp" android:textColor="#F9EBC6" android:layout_marginTop="8dp" android:background="@android:color/transparent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" /> <!-- Subtitle Text --> <TextView android:id="@+id/sub_title_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="首次开通" android:textSize="10dp" android:textColor="#CCCCCC" android:paddingStart="5dp" android:paddingTop="2dp" android:paddingEnd="5dp" android:paddingBottom="2dp" android:background="@drawable/round_transition_gray_bg" app:layout_constraintTop_toBottomOf="@id/title_text" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="85dp" android:layout_marginTop="-20dp" /> <!-- Price Text --> <TextView android:id="@+id/price_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="¥9.9" android:textSize="40sp" android:textColor="#F9EBC6" android:layout_marginTop="0dp" android:layout_marginLeft="150dp" android:background="@android:color/transparent" app:layout_constraintTop_toBottomOf="@id/sub_title_text" app:layout_constraintStart_toStartOf="parent" /> <!-- Next Price Text --> <TextView android:id="@+id/next_price_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="次月起12元/月" android:textSize="14sp" android:textColor="#CCCCCC" android:layout_marginTop="-30dp" android:background="@android:color/transparent" app:layout_constraintTop_toBottomOf="@id/price_text" app:layout_constraintStart_toStartOf="parent" /> <!-- Auto Renew Text --> <TextView android:id="@+id/auto_renew_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="自动续费可随时取消" android:textSize="12sp" android:textColor="#CCCCCC" android:layout_marginTop="4dp" android:background="@android:color/transparent" app:layout_constraintTop_toBottomOf="@id/next_price_text" app:layout_constraintStart_toStartOf="parent" /> <!-- <TextView--> <!-- android:id="@+id/auto_renew_text2"--> <!-- android:layout_width="wrap_content"--> <!-- android:layout_height="wrap_content"--> <!-- android:text="活动须知"--> <!-- android:textSize="12sp"--> <!-- android:textColor="#CCCCCC"--> <!-- android:layout_marginTop="4dp"--> <!-- android:background="@android:color/transparent"--> <!-- app:layout_constraintTop_toBottomOf="@id/auto_renew_text"--> <!-- app:layout_constraintStart_toStartOf="parent" />--> <!-- <TextView--> <!-- android:id="@+id/auto_renew_text3"--> <!-- android:layout_width="wrap_content"--> <!-- android:layout_height="wrap_content"--> <!-- android:text=">"--> <!-- android:textSize="16sp"--> <!-- android:textColor="#CCCCCC"--> <!-- android:layout_marginTop="0dp"--> <!-- android:background="@android:color/transparent"--> <!-- android:layout_marginLeft="60dp"--> <!-- app:layout_constraintTop_toBottomOf="@id/auto_renew_text"--> <!-- app:layout_constraintStart_toStartOf="parent" />--> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.cardview.widget.CardView> <TextView android:id="@+id/first_month_tag" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="0dp" android:layout_marginRight="5dp" android:scaleType="centerCrop" android:layout_gravity="end|top" android:text="首月限时特惠" android:textColor="#FFFFFF" android:padding="4dp" android:elevation="4dp" android:background="@drawable/round_red_bg" /> </androidx.cardview.widget.CardView> app/src/main/res/layout/item_card_single_month.xml
对比新文件 @@ -0,0 +1,55 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="160dp" android:layout_height="wrap_content" android:layout_margin="8dp" android:background="@android:color/transparent" app:cardBackgroundColor="@android:color/transparent" app:cardElevation="0dp" app:cardUseCompatPadding="false" > <androidx.cardview.widget.CardView android:id="@+id/vip_month_card_view" android:layout_width="160dp" android:layout_height="140dp" android:padding="8dp" android:layout_marginTop="10dp" android:layout_marginEnd="20dp" android:background="@android:color/transparent" android:foreground="@drawable/gray_border_shape" app:cardBackgroundColor="@android:color/transparent" app:cardCornerRadius="16dp" app:cardElevation="0dp" app:cardUseCompatPadding="false"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginRight="20dp" android:gravity="center" android:orientation="vertical" android:padding="16dp"> <TextView android:id="@+id/single_month_title_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="1个月" android:textColor="#F9EBC6" android:textSize="18sp" /> <TextView android:id="@+id/single_month_price_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="¥15" android:textColor="#F9EBC6" android:textSize="40sp" /> </LinearLayout> </androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView> app/src/main/res/layout/item_card_yearly.xml
对比新文件 @@ -0,0 +1,81 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="160dp" android:layout_height="wrap_content" android:layout_margin="8dp" android:background="@android:color/transparent" app:cardBackgroundColor="@android:color/transparent" app:cardElevation="0dp" app:cardUseCompatPadding="false" > <androidx.cardview.widget.CardView android:id="@+id/vip_year_card_view" 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="140dp" android:layout_marginTop="10dp" app:cardCornerRadius="16dp" android:foreground="@drawable/gray_border_shape" app:cardBackgroundColor="@android:color/transparent" app:cardElevation="0dp" app:cardUseCompatPadding="false"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:gravity="center" android:padding="16dp"> <TextView android:id="@+id/yearly_title_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="年卡" android:textSize="18sp" android:textColor="#F9EBC6" android:layout_marginTop="8dp"/> <TextView android:id="@+id/yearly_price_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="¥108/年" android:textSize="30sp" android:textColor="#F9EBC6" android:layout_marginTop="8dp"/> <TextView android:id="@+id/yearly_original_price_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="¥168" android:textSize="12sp" android:textColor="#CCCCCC" android:layout_marginTop="4dp" /> </LinearLayout> </androidx.cardview.widget.CardView> <TextView android:id="@+id/discount_tag" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="0dp" android:layout_marginRight="5dp" android:scaleType="centerCrop" android:layout_gravity="end|top" android:text="折合9元/月" android:textColor="#FFFFFF" android:padding="4dp" android:elevation="4dp" android:background="@drawable/round_red_bg" /> </androidx.cardview.widget.CardView> app/src/main/res/navigation/nav_graph.xml
对比新文件 @@ -0,0 +1,28 @@ <?xml version="1.0" encoding="utf-8"?> <navigation 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:id="@+id/nav_graph" app:startDestination="@id/FirstFragment"> <fragment android:id="@+id/FirstFragment" android:name="com.example.firstapp.activity.FirstFragment" android:label="@string/first_fragment_label" tools:layout="@layout/fragment_first"> <action android:id="@+id/action_FirstFragment_to_SecondFragment" app:destination="@id/SecondFragment" /> </fragment> <fragment android:id="@+id/SecondFragment" android:name="com.example.firstapp.activity.SecondFragment" android:label="@string/second_fragment_label" tools:layout="@layout/fragment_second"> <action android:id="@+id/action_SecondFragment_to_FirstFragment" app:destination="@id/FirstFragment" /> </fragment> </navigation> app/src/main/res/values-land/dimens.xml
对比新文件 @@ -0,0 +1,3 @@ <resources> <dimen name="fab_margin">48dp</dimen> </resources> app/src/main/res/values-w1240dp/dimens.xml
对比新文件 @@ -0,0 +1,3 @@ <resources> <dimen name="fab_margin">200dp</dimen> </resources> app/src/main/res/values-w600dp/dimens.xml
对比新文件 @@ -0,0 +1,3 @@ <resources> <dimen name="fab_margin">48dp</dimen> </resources> app/src/main/res/values/dimens.xml
@@ -5,4 +5,5 @@ <dimen name="list_item_spacing">16dp</dimen> <dimen name="list_item_spacing_half">8dp</dimen> <dimen name="heatmap_cell_size">12dp</dimen> <dimen name="fab_margin">16dp</dimen> </resources> app/src/main/res/xml/network_security_config.xml
@@ -5,6 +5,7 @@ <domain includeSubdomains="true">192.168.1.213</domain> <domain includeSubdomains="true">192.168.1.198</domain> <domain includeSubdomains="true">192.168.1.199</domain> <domain includeSubdomains="true">192.168.1.201</domain> <!-- 可添加其他域名或IP(如192.168.0.101) --> <!-- 如果本地服务使用自签名证书,需在 network_security_config.xml 中信任该证书:--> <!-- <trust-anchors>-->