代码分享:lua实现悬浮底栏(适用FusionApp2.0)

分享一下和DeepSeek一起完成的屎山

–[[
基于Q弹底栏(ID:5245)修改,DeepSeek辅助修改
代码可能不规范,甚至有点乱
主要修改内容:
1.适配FusionApp2.0,加入隐藏默认底栏,和fa独有view切换
2.圆角改16dp
3.改为悬浮布局(标准描述我不太懂,大概就是可以在原有布局基础上直接require或其他方法引用),运行后会在原有布局上生成悬浮底栏,而不会覆盖
4.移除部分动画
5.加入显示动画
]]

require “import”
import “android.graphics.Color”
import “android.view.View”
import “android.widget.ImageView”
import “android.view.animation.OvershootInterpolator”
import “android.widget.TextView”
import “android.animation.ObjectAnimator”
import “android.widget.FrameLayout”
import “androidx.cardview.widget.CardView”
import “android.widget.LinearLayout”
import “android.animation.LayoutTransition”

–这里是为了方便适配主题系统,实际应用中可以加入深色模式判断
背景色_底栏=”#ffffff”
文字色_底栏=”#1e1e1e”

–隐藏FusionApp2.0自带底栏,非必须(隐藏底栏)
activity.uiManager.indicatorView.setVisibility(8)

— 创建悬浮底栏布局
local floatBottomBar = loadlayout{
  FrameLayout,
  layout_width=”match_parent”,
  layout_height=”match_parent”,
  background=’#00000000′,
  {
    LinearLayout,
    orientation=”vertical”,
    layout_width=”match_parent”,
    layout_height=”match_parent”,
    gravity=”bottom”,
    {
      LinearLayout,
      orientation=’horizontal’,
      layout_width=’match_parent’,
      layout_height=’wrap’,
      gravity=”center”,
      layout_marginBottom=”20dp”,
      id=”bottomBar”,
      layoutTransition=LayoutTransition()
        .enableTransitionType(LayoutTransition.CHANGING)
        .setDuration(LayoutTransition.CHANGE_APPEARING, 400)
        .setDuration(LayoutTransition.CHANGE_DISAPPEARING, 400),
      — 首页按钮
      {
        CardView,
        id=”homeCard”,
        layout_margin=’8dp’,
        elevation=’2dp’,
        layout_width=’wrap’,
        layout_height=’wrap’,
        CardBackgroundColor=背景色_底栏,
        radius=’16dp’,
        {
          LinearLayout,
          id=”homeLayout”,
          orientation=’horizontal’,
          layout_width=’wrap’,
          layout_height=’wrap’,
          background=’#00FFFFFF’,
          layout_margin=’15dp’,
          layoutTransition=LayoutTransition()
            .enableTransitionType(LayoutTransition.CHANGING)
            .setDuration(LayoutTransition.CHANGE_APPEARING, 400)
            .setDuration(LayoutTransition.CHANGE_DISAPPEARING, 400),
          {
            ImageView,
            id=”homeIcon”,
            src=’home’,
            layout_width=’24dp’,
            layout_height=’24dp’,
            scaleType=’fitXY’,
          },
          {
            TextView,
            id=”homeText”,
            gravity=’center’,
            layout_marginLeft=’8dp’,
            layout_marginRight=’4dp’,
            layout_width=’wrap’,
            layout_height=’wrap’,
            textColor=文字色_底栏,
            text=’首页’,
            visibility=8,
            textSize=’14dp’,
          },
        },
      },
      — 资源聚合按钮
      {
        CardView,
        id=”dashboardCard”,
        layout_margin=’8dp’,
        elevation=’2dp’,
        layout_width=’wrap’,
        layout_height=’wrap’,
        CardBackgroundColor=背景色_底栏,
        radius=’16dp’,
        {
          LinearLayout,
          id=”dashboardLayout”,
          orientation=’horizontal’,
          layout_width=’wrap’,
          layout_height=’wrap’,
          background=’#00FFFFFF’,
          layout_margin=’15dp’,
          layoutTransition=LayoutTransition()
            .enableTransitionType(LayoutTransition.CHANGING)
            .setDuration(LayoutTransition.CHANGE_APPEARING, 400)
            .setDuration(LayoutTransition.CHANGE_DISAPPEARING, 400),
          {
            ImageView,
            id=”dashboardIcon”,
            src=’dashboard’,
            layout_width=’24dp’,
            layout_height=’24dp’,
            scaleType=’fitXY’,
          },
          {
            TextView,
            id=”dashboardText”,
            gravity=’center’,
            layout_marginLeft=’8dp’,
            layout_marginRight=’4dp’,
            layout_width=’wrap’,
            layout_height=’wrap’,
            textColor=文字色_底栏,
            text=’资源聚合’,
            visibility=8,
            textSize=’14dp’,
          },
        },
      },
      — 超级功能按钮
      {
        CardView,
        id=”puzzleCard”,
        layout_margin=’8dp’,
        elevation=’2dp’,
        layout_width=’wrap’,
        layout_height=’wrap’,
        CardBackgroundColor=背景色_底栏,
        radius=’16dp’,
        {
          LinearLayout,
          id=”puzzleLayout”,
          orientation=’horizontal’,
          layout_width=’wrap’,
          layout_height=’wrap’,
          background=’#00FFFFFF’,
          layout_margin=’15dp’,
          layoutTransition=LayoutTransition()
            .enableTransitionType(LayoutTransition.CHANGING)
            .setDuration(LayoutTransition.CHANGE_APPEARING, 400)
            .setDuration(LayoutTransition.CHANGE_DISAPPEARING, 400),
          {
            ImageView,
            id=”puzzleIcon”,
            src=’puzzle’,
            layout_width=’24dp’,
            layout_height=’24dp’,
            scaleType=’fitXY’,
          },
          {
            TextView,
            id=”puzzleText”,
            gravity=’center’,
            layout_marginLeft=’8dp’,
            layout_marginRight=’4dp’,
            layout_width=’wrap’,
            layout_height=’wrap’,
            textColor=文字色_底栏,
            text=’超级功能’,
            visibility=8,
            textSize=’14dp’,
          },
        },
      },
      — 用户信息按钮
      {
        CardView,
        id=”personCard”,
        layout_margin=’8dp’,
        elevation=’2dp’,
        layout_width=’wrap’,
        layout_height=’wrap’,
        CardBackgroundColor=背景色_底栏,
        radius=’16dp’,
        {
          LinearLayout,
          id=”personLayout”,
          orientation=’horizontal’,
          layout_width=’wrap’,
          layout_height=’wrap’,
          background=’#00FFFFFF’,
          layout_margin=’15dp’,
          layoutTransition=LayoutTransition()
            .enableTransitionType(LayoutTransition.CHANGING)
            .setDuration(LayoutTransition.CHANGE_APPEARING, 400)
            .setDuration(LayoutTransition.CHANGE_DISAPPEARING, 400),
          {
            ImageView,
            id=”personIcon”,
            src=’person’,
            layout_width=’24dp’,
            layout_height=’24dp’,
            scaleType=’fitXY’,
          },
          {
            TextView,
            id=”personText”,
            gravity=’center’,
            layout_marginLeft=’8dp’,
            layout_marginRight=’4dp’,
            layout_width=’wrap’,
            layout_height=’wrap’,
            textColor=文字色_底栏,
            text=’用户信息’,
            visibility=8,
            textSize=’14dp’,
          },
        },
      },
    },
  },
}

— 添加到Activity
local params = FrameLayout.LayoutParams(
  FrameLayout.LayoutParams.MATCH_PARENT,
  FrameLayout.LayoutParams.MATCH_PARENT
)
activity.addContentView(floatBottomBar, params)

— 上升显示动画
bottomBar.setTranslationY(200)
bottomBar.setAlpha(0)
bottomBar.animate()
  .translationY(0)
  .alpha(1)
  .setDuration(500)
  .setInterpolator(OvershootInterpolator(1.2))
  .start()

— 存储原始宽度
local originalWidths = {}

— 初始化记录原始宽度
local function initWidths()
  originalWidths[homeCard] = homeCard.getWidth()
  originalWidths[dashboardCard] = dashboardCard.getWidth()
  originalWidths[puzzleCard] = puzzleCard.getWidth()
  originalWidths[personCard] = personCard.getWidth()
end

— 等待布局完成后再获取宽度
bottomBar.post(function()
  initWidths()
end)

— 动画相关变量
local isAnimating = false
local TimeS = 300
local ReturnTime = 10

— 挤压动画函数
local function squeezeAnimation(selectedView, interpolator)
  if isAnimating then return end
  isAnimating = true
 
  local parent = bottomBar
  if not parent then return end
 
  local leftViews = {}
  local rightViews = {}
  local selectedIndex = -1
 
  for i = 0, parent.getChildCount() – 1 do
    local view = parent.getChildAt(i)
    if view == selectedView then
      selectedIndex = i
      break
    end
  end
 
  if selectedIndex == -1 then
    isAnimating = false
    return
  end
 
  for i = 0, parent.getChildCount() – 1 do
    local view = parent.getChildAt(i)
    if i < selectedIndex then
      table.insert(leftViews, view)
    elseif i > selectedIndex then
      table.insert(rightViews, view)
    end
  end
 
  local function getViewWidth(view)
    return originalWidths[view] or view.getWidth()
  end
 
  — 挤压移动动画已注释
  –[[
  for i, view in ipairs(leftViews) do
    local viewWidth = getViewWidth(view)
    local moveDistance = -(viewWidth * 0.3 + 10) * (1 – i / #leftViews * 0.5)
    local animator = ObjectAnimator.ofFloat(view, “translationX”, {0, moveDistance})
    animator.setDuration(TimeS)
    animator.setInterpolator(interpolator)
    animator.start()
  end
 
  for i, view in ipairs(rightViews) do
    local viewWidth = getViewWidth(view)
    local moveDistance = (viewWidth * 0.3 + 10) * (1 – i / #rightViews * 0.5)
    local animator = ObjectAnimator.ofFloat(view, “translationX”, {0, moveDistance})
    animator.setDuration(TimeS)
    animator.setInterpolator(interpolator)
    animator.start()
  end
  ]]
 
  local returnAnim = function()
    for i, view in ipairs(leftViews) do
      local animator = ObjectAnimator.ofFloat(view, “translationX”, {view.getTranslationX(), 0})
      animator.setDuration(TimeS)
      animator.setInterpolator(interpolator)
      animator.start()
    end
   
    for i, view in ipairs(rightViews) do
      local animator = ObjectAnimator.ofFloat(view, “translationX”, {view.getTranslationX(), 0})
      animator.setDuration(TimeS)
      animator.setInterpolator(interpolator)
      animator.start()
    end
   
    isAnimating = false
  end
 
  selectedView.postDelayed(returnAnim, TimeS + ReturnTime)
end

— 重置所有按钮状态
local function resetAllButtons()
  homeText.setVisibility(View.GONE)
  dashboardText.setVisibility(View.GONE)
  puzzleText.setVisibility(View.GONE)
  personText.setVisibility(View.GONE)
 
  homeIcon.setColorFilter(Color.parseColor(“#757575”))
  dashboardIcon.setColorFilter(Color.parseColor(“#757575”))
  puzzleIcon.setColorFilter(Color.parseColor(“#757575”))
  personIcon.setColorFilter(Color.parseColor(“#757575”))
end

— 设置选中状态
local function setSelected(selectedIcon, selectedText)
  selectedText.setVisibility(View.VISIBLE)
  selectedText.setTextColor(Color.parseColor(“#424242”))
  selectedIcon.setColorFilter(Color.parseColor(“#424242”))
end

— 插值器
import “android.view.animation.OvershootInterpolator”
local interpolator = OvershootInterpolator(2.0)
local viewPager=uiManager.viewPager
— 按钮点击事件
homeCard.onClick = function()
  if isAnimating then return end
  squeezeAnimation(homeCard, interpolator)
  resetAllButtons()
  setSelected(homeIcon, homeText)
  viewPager.setCurrentItem(0)–这个是fa独有的
end

dashboardCard.onClick = function()
  if isAnimating then return end
  squeezeAnimation(dashboardCard, interpolator)
  resetAllButtons()
  setSelected(dashboardIcon, dashboardText)
  viewPager.setCurrentItem(1)
end

puzzleCard.onClick = function()
  if isAnimating then return end
  squeezeAnimation(puzzleCard, interpolator)
  resetAllButtons()
  setSelected(puzzleIcon, puzzleText)
  viewPager.setCurrentItem(2)
end

personCard.onClick = function()
  if isAnimating then return end
  squeezeAnimation(personCard, interpolator)
  resetAllButtons()
  setSelected(personIcon, personText)
  viewPager.setCurrentItem(3)
end

— 设置默认选中首页
homeCard.performClick()

— 清理资源
function onDestroy()
  if floatBottomBar and floatBottomBar.getParent() then
    floatBottomBar.getParent().removeView(floatBottomBar)
  end
end

发布者:小特_XT

欢迎访问我的网站:https://xiaote.data.blog/

留下评论

通过 WordPress.com 设计一个这样的站点
从这里开始