From 85d11d6cd12abdd1e1f5f7516a7fb53a4826633f Mon Sep 17 00:00:00 2001
From: cloudroam <cloudroam>
Date: 星期二, 15 四月 2025 09:17:18 +0800
Subject: [PATCH] add: 消息提醒

---
 app/src/main/java/com/example/firstapp/ui/invitation/InvitationActivity.kt |  384 +++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 334 insertions(+), 50 deletions(-)

diff --git a/app/src/main/java/com/example/firstapp/ui/invitation/InvitationActivity.kt b/app/src/main/java/com/example/firstapp/ui/invitation/InvitationActivity.kt
index 51fc5fc..353707d 100644
--- a/app/src/main/java/com/example/firstapp/ui/invitation/InvitationActivity.kt
+++ b/app/src/main/java/com/example/firstapp/ui/invitation/InvitationActivity.kt
@@ -1,98 +1,382 @@
 package com.example.firstapp.ui.invitation
 
+import android.content.ClipData
+import android.content.ClipboardManager
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
 import android.os.Bundle
 import android.os.Handler
 import android.os.Looper
-import android.util.DisplayMetrics
+import android.text.Html
+import android.util.TypedValue
+import android.view.View
+import android.widget.Button
+import android.widget.TextView
+import android.widget.Toast
 import androidx.appcompat.app.AppCompatActivity
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.LinearSmoothScroller
 import androidx.recyclerview.widget.RecyclerView
 import com.example.firstapp.R
 import com.example.firstapp.adapter.InvitationAdapter
+import com.example.firstapp.adapter.InvitationRecordAdapter
 import com.example.firstapp.entity.InvitationRecord
-import java.text.SimpleDateFormat
-import java.util.Locale
-import java.util.concurrent.Executors
+import com.example.firstapp.utils.PreferencesManager
+import kotlin.math.abs
 
 class InvitationActivity : AppCompatActivity() {
 
-    private lateinit var recyclerView: RecyclerView
+    private lateinit var recyclerSuccessView: RecyclerView
+    private lateinit var recyclerRecordView: RecyclerView
     private lateinit var adapter: InvitationAdapter
-    private var currentPosition = 0
+    private lateinit var recordadapter: InvitationRecordAdapter
+    private val data = mutableListOf<InvitationRecord>()
+    private val recorddata = mutableListOf<InvitationRecord>()
     private val handler = Handler(Looper.getMainLooper())
-    private lateinit var scrollRunnable: Runnable
+    private val scrollInterval = 3000L
+    private var currentScrollPosition = 0
+    private var currentRecordScrollPosition = 0
+    private var itemHeight = 0 // 动态存储item高度
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.activity_invitation_main)
 
-        setupRecyclerView()
+        // 初始化视图
+        initViews()
+
+        //初始化Adapter
+        initSuccessAdapter()
+
+        initRecorddapter()
+
+        //加载数据
         loadData()
-        setupAutoScroll()
+
+        loadRecordData()
+
+        //启动轮播
+        startAutoScroll()
+
+        //分享
+        val btnInvite = findViewById<Button>(R.id.btnInvite)
+        btnInvite.setOnClickListener {
+            shareImageToWechat()
+        }
+
+        //邀请码
+        val invitationCodeText = findViewById<TextView>(R.id.invitationCodeText)
+        invitationCodeText.text = "A1B2"
+        //invitationCodeText.text = formatInvitationCode(PreferencesManager.getInviteCode());
+        findViewById<Button>(R.id.copyButton).setOnClickListener {
+            val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
+            val clip = ClipData.newPlainText(
+                "邀请码",
+                invitationCodeText.text.toString().replace(" ", "") // 复制时去掉空格
+            )
+            clipboard.setPrimaryClip(clip)
+            Toast.makeText(this, "已复制邀请码", Toast.LENGTH_SHORT).show()
+        }
     }
 
-    private fun setupRecyclerView() {
-        recyclerView = findViewById(R.id.invitationsuccessRecyclerView)
-        recyclerView.layoutManager = LinearLayoutManager(this).apply {
-            stackFromEnd = false // 从顶部开始布局
+    private fun initViews() {
+        findViewById<TextView>(R.id.tv_notic).apply {
+            text = Html.fromHtml(getString(R.string.invite_reward_text), Html.FROM_HTML_MODE_LEGACY)
         }
-        adapter = InvitationAdapter()
-        recyclerView.adapter = adapter
+        recyclerSuccessView = findViewById(R.id.invitationsuccessRecyclerView)
+        addSuccessListener()
+
+        recyclerRecordView = findViewById(R.id.invitationrecordRecyclerView)
+        addRecordListener()
+    }
+
+    private fun addSuccessListener() {
+        recyclerSuccessView.viewTreeObserver.addOnGlobalLayoutListener {
+            if (recyclerSuccessView.childCount > 0) {
+                // 计算预期高度(60dp转px)
+                val expectedHeight = dpToPx(60f)
+                if (itemHeight != expectedHeight) {
+                    // 修正所有item的高度
+                    for (i in 0 until recyclerSuccessView.childCount) {
+                        recyclerSuccessView.getChildAt(i).layoutParams.height = expectedHeight
+                    }
+                    // 请求重新布局
+                    recyclerSuccessView.requestLayout()
+                    itemHeight = expectedHeight
+                }
+            }
+        }
+        recyclerSuccessView.layoutManager = object : LinearLayoutManager(this@InvitationActivity) {
+            override fun onMeasure(
+                recycler: RecyclerView.Recycler, state: RecyclerView.State,
+                widthSpec: Int, heightSpec: Int
+            ) {
+                if (itemHeight > 0) {
+                    // 使用实际测量的高度
+                    setMeasuredDimension(
+                        View.resolveSize(widthSpec, width),
+                        itemHeight
+                    )
+                } else {
+                    // 默认高度60dp
+                    val defaultHeight = TypedValue.applyDimension(
+                        TypedValue.COMPLEX_UNIT_DIP, 60f,
+                        resources.displayMetrics
+                    ).toInt()
+                    setMeasuredDimension(
+                        View.resolveSize(widthSpec, width),
+                        defaultHeight
+                    )
+                }
+            }
+        }
+    }
+
+    private fun addRecordListener() {
+        recyclerRecordView.viewTreeObserver.addOnGlobalLayoutListener {
+            if (recyclerSuccessView.childCount > 0) {
+                // 计算预期高度(60dp转px)
+                val expectedHeight = dpToPx(60f)
+                if (itemHeight != expectedHeight) {
+                    // 修正所有item的高度
+                    for (i in 0 until recyclerSuccessView.childCount) {
+                        recyclerSuccessView.getChildAt(i).layoutParams.height = expectedHeight
+                    }
+                    // 请求重新布局
+                    recyclerSuccessView.requestLayout()
+                    itemHeight = expectedHeight
+                }
+            }
+        }
+        recyclerRecordView.layoutManager = object : LinearLayoutManager(this@InvitationActivity) {
+            override fun onMeasure(
+                recycler: RecyclerView.Recycler, state: RecyclerView.State,
+                widthSpec: Int, heightSpec: Int
+            ) {
+                if (itemHeight > 0) {
+                    // 使用实际测量的高度
+                    setMeasuredDimension(
+                        View.resolveSize(widthSpec, width),
+                        itemHeight
+                    )
+                } else {
+                    // 默认高度60dp
+                    val defaultHeight = TypedValue.applyDimension(
+                        TypedValue.COMPLEX_UNIT_DIP, 60f,
+                        resources.displayMetrics
+                    ).toInt()
+                    setMeasuredDimension(
+                        View.resolveSize(widthSpec, width),
+                        defaultHeight
+                    )
+                }
+            }
+        }
+    }
+
+    private fun initSuccessAdapter() {
+        adapter = InvitationAdapter(this, data).apply {
+            registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
+                override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
+                    // 数据插入时检查高度
+                    recyclerSuccessView.post {
+                        if (recyclerSuccessView.childCount > 0) {
+                            itemHeight = recyclerSuccessView.getChildAt(0).height
+                        }
+                    }
+                }
+            })
+        }
+        recyclerSuccessView.adapter = adapter
+    }
+
+    private fun initRecorddapter() {
+        recordadapter = InvitationRecordAdapter(this, recorddata).apply {
+            registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
+                override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
+                    // 数据插入时检查高度
+                    recyclerRecordView.post {
+                        if (recyclerRecordView.childCount > 0) {
+                            itemHeight = recyclerRecordView.getChildAt(0).height
+                        }
+                    }
+                }
+            })
+        }
+        recyclerRecordView.adapter = recordadapter
     }
 
     private fun loadData() {
-        val mockData = listOf(
-            InvitationRecord("H****e", "获得了3天会员"),
-            InvitationRecord("U****r", "获得了7天会员"),
-            InvitationRecord("A****e", "获得了免广告特权"),
-            InvitationRecord("B****d", "获得了3天会员"),
-            InvitationRecord("C****o", "获得了7天会员")
+        data.clear()
+        data.addAll(
+            listOf(
+                InvitationRecord("H****e", "获得了1天会员", "已注册"),
+                InvitationRecord("U****r", "获得了2天会员", "已注册"),
+                InvitationRecord("A****e", "获得了免广告特权", "已注册"),
+                InvitationRecord("B****e", "获得了3天会员", "已注册"),
+                InvitationRecord("C****o", "获得了4天会员", "已注册")
+            )
         )
-        adapter.submitList(mockData)
+        adapter.notifyDataSetChanged()
     }
 
-    private fun setupAutoScroll() {
-        scrollRunnable = object : Runnable {
-            override fun run() {
-                if (currentPosition < adapter.itemCount - 1) {
-                    currentPosition++
-                    smoothScrollToPosition(currentPosition)
-                } else {
-                    // 滚动到底部后回到顶部
-                    currentPosition = 0
-                    recyclerView.scrollToPosition(0)
+    private fun loadRecordData() {
+        recorddata.clear()
+        recorddata.addAll(
+            listOf(
+                InvitationRecord("M****e", "", "未注册"),
+                InvitationRecord("Q****r", "", "已注册"),
+                InvitationRecord("W****e", "", "未注册"),
+                InvitationRecord("E****e", "", "未注册"),
+                InvitationRecord("R****o", "", "已注册")
+            )
+        )
+        recordadapter.notifyDataSetChanged()
+    }
+
+    // 分享资源图片到微信
+    private fun shareImageToWechat() {
+        try {
+            // 获取资源图片的URI
+            val imageUri = Uri.parse("android.resource://${packageName}/${R.drawable.location}")
+
+            val intent = Intent().apply {
+                action = Intent.ACTION_SEND
+                type = "image/*"
+                putExtra(Intent.EXTRA_STREAM, imageUri)
+                flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
+                setPackage("com.tencent.mm") // 指定微信包名
+            }
+
+            // 创建选择器,即使微信不可用也能选择其他应用
+            val chooserIntent = Intent.createChooser(intent, "分享邀请图片")
+
+            // 检查是否有应用能处理这个Intent
+            if (intent.resolveActivity(packageManager) != null) {
+                startActivity(chooserIntent)
+            } else {
+                Toast.makeText(this, "未找到可分享的应用", Toast.LENGTH_SHORT).show()
+            }
+        } catch (e: Exception) {
+            Toast.makeText(this, "分享失败: ${e.message}", Toast.LENGTH_SHORT).show()
+        }
+    }
+
+    private fun formatInvitationCode(code: String): String {
+        return if (code.length > 2) {
+            code.chunked(2).joinToString(" ")
+        } else {
+            code
+        }
+    }
+
+    private val scrollRunnable = object : Runnable {
+        override fun run() {
+            if (data.isEmpty() || itemHeight <= 0) {
+                handler.postDelayed(this, scrollInterval)
+                return
+            }
+
+            // 使用取模运算确保位置在有效范围内
+            currentScrollPosition++
+            currentRecordScrollPosition++
+
+            // 创建自定义平滑滚动器
+            val smoothScroller = object : LinearSmoothScroller(this@InvitationActivity) {
+                override fun getVerticalSnapPreference(): Int = SNAP_TO_START
+
+                override fun calculateDyToMakeVisible(view: View, snapPreference: Int): Int {
+                    // 计算需要滚动的距离,确保完整显示下一个item
+                    val top = view.top
+                    val height = view.height
+                    return when {
+                        snapPreference == SNAP_TO_START -> -top
+                        snapPreference == SNAP_TO_END -> -(top - (recyclerSuccessView.height - height))
+                        else -> -(top - (recyclerSuccessView.height / 2 - height / 2))
+                    }
                 }
-                handler.postDelayed(this, 2000)
+
+                override fun calculateTimeForScrolling(dx: Int): Int {
+                    // 根据滚动距离动态计算时间,保持匀速
+                    return maxOf((500f * abs(dx) / itemHeight).toInt(), 200)
+                }
+            }.apply {
+                targetPosition = currentScrollPosition
             }
+
+            val smoothRecordScroller = object : LinearSmoothScroller(this@InvitationActivity) {
+                override fun getVerticalSnapPreference(): Int = SNAP_TO_START
+
+                override fun calculateDyToMakeVisible(view: View, snapPreference: Int): Int {
+                    // 计算需要滚动的距离,确保完整显示下一个item
+                    val top = view.top
+                    val height = view.height
+                    return when {
+                        snapPreference == SNAP_TO_START -> -top
+                        snapPreference == SNAP_TO_END -> -(top - (recyclerRecordView.height - height))
+                        else -> -(top - (recyclerRecordView.height / 2 - height / 2))
+                    }
+                }
+
+                override fun calculateTimeForScrolling(dx: Int): Int {
+                    // 根据滚动距离动态计算时间,保持匀速
+                    return maxOf((500f * abs(dx) / itemHeight).toInt(), 200)
+                }
+            }.apply {
+                targetPosition = currentRecordScrollPosition
+            }
+
+            // 启动平滑滚动
+            recyclerSuccessView.layoutManager?.startSmoothScroll(smoothScroller)
+
+            recyclerRecordView.layoutManager?.startSmoothScroll(smoothRecordScroller)
+
+            // 更智能的边界检测
+            (recyclerSuccessView.layoutManager as? LinearLayoutManager)?.let { lm ->
+                val lastVisible = lm.findLastVisibleItemPosition()
+                val totalItems = adapter.itemCount
+
+                // 当接近"虚拟列表"末尾时,跳转到中间位置
+                if (lastVisible >= totalItems - 3) {
+                    val jumpPosition = (totalItems / 2) * (Int.MAX_VALUE / totalItems)
+                    currentScrollPosition = jumpPosition
+                    recyclerSuccessView.scrollToPosition(jumpPosition)
+                }
+            }
+
+            (recyclerRecordView.layoutManager as? LinearLayoutManager)?.let { lm ->
+                val lastVisible = lm.findLastVisibleItemPosition()
+                val totalItems = recordadapter.itemCount
+
+                // 当接近"虚拟列表"末尾时,跳转到中间位置
+                if (lastVisible >= totalItems - 3) {
+                    val jumpPosition = (totalItems / 2) * (Int.MAX_VALUE / totalItems)
+                    currentRecordScrollPosition = jumpPosition
+                    recyclerRecordView.scrollToPosition(jumpPosition)
+                }
+            }
+
+            handler.postDelayed(this, scrollInterval)
         }
-        startAutoScroll()
     }
 
-    private fun smoothScrollToPosition(position: Int) {
-        val layoutManager = recyclerView.layoutManager as LinearLayoutManager
-        val smoothScroller = object : LinearSmoothScroller(this) {
-            override fun getVerticalSnapPreference(): Int = SNAP_TO_START
+    private fun pxToDp(px: Int, context: Context): Int {
+        return (px / (context.resources.displayMetrics.density)).toInt()
+    }
 
-            override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics): Float {
-                return 100f / displayMetrics.densityDpi // 控制滚动速度
-            }
-        }
-        smoothScroller.targetPosition = position
-        layoutManager.startSmoothScroll(smoothScroller)
+    private fun dpToPx(dp: Float): Int {
+        return (dp * resources.displayMetrics.density).toInt()
     }
 
     private fun startAutoScroll() {
-        handler.postDelayed(scrollRunnable, 2000)
-    }
-
-    private fun stopAutoScroll() {
-        handler.removeCallbacks(scrollRunnable)
+        handler.removeCallbacks(scrollRunnable) // 先移除之前的回调
+        handler.postDelayed(scrollRunnable, scrollInterval)
     }
 
     override fun onPause() {
+        handler.removeCallbacks(scrollRunnable)
         super.onPause()
-        stopAutoScroll()
     }
 
     override fun onResume() {

--
Gitblit v1.9.3