簡體   English   中英

Android MaterialCardView 的投影/高度在旋轉 180 度時消失

[英]Android MaterialCardView's drop shadow/elevation disappears when rotating it 180 degrees

總結問題:

我正在開發一個繪畫應用程序,在這個應用程序中,用戶可以選擇旋轉 canvas,這個功能在某些情況下很有用。

我遇到的問題是,當我將承載畫布/位圖的CardView旋轉 180 度時,陰影會丟失。 當我將CardView旋轉 90 度時,我沒有遇到這個問題,只有 180 度。

描述你嘗試過的東西

我嘗試了很多東西,例如給 CardView 更多空間以便顯示投影,或者在將代碼旋轉 180 度后手動應用代碼中的投影,但它沒有奏效。

顯示一些代碼

這是負責旋轉CardView的代碼(非常簡單):

fun CanvasActivity.rotate(rotationValue: RotationValue, animate: Boolean = false) {
    rotate(rotationValue.degrees, rotationValue.clockwise, animate)
}

fun CanvasActivity.rotate(degrees: Int, clockwise: Boolean = true, animate: Boolean = false) {
    val rotationAmount = if (clockwise) {
        (binding.activityCanvasCardView.rotation + degrees)
    } else {
        (binding.activityCanvasCardView.rotation - degrees)
    }

    if (animate) {
        binding.activityCanvasCardView
            .animate()
            .rotation(rotationAmount)
    } else {
        binding.activityCanvasCardView.rotation = rotationAmount
    }
}

activity_canvas

<?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="@color/fragment_background_color_daynight"
    tools:context=".activities.canvas.CanvasActivity">
    <!-- This view is here to ensure that when the user zooms in, there is no overlap -->
    <View
        android:elevation="20dp"
        android:outlineProvider="none"
        android:id="@+id/activityCanvas_topView"
        android:layout_width="0dp"
        android:layout_height="90dp"
        android:background="@color/fragment_background_color_daynight"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <!-- The ColorSwitcherView is a view I created which helps
         simplify the code for controlling the user's primary/secondary color -->
    <com.therealbluepandabear.pixapencil.customviews.colorswitcherview.ColorSwitcherView
        android:id="@+id/activityCanvas_colorSwitcherView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:elevation="20dp"
        android:outlineProvider="none"
        app:isPrimarySelected="true"
        app:layout_constraintEnd_toEndOf="@+id/activityCanvas_topView"
        app:layout_constraintTop_toTopOf="@+id/activityCanvas_colorPickerRecyclerView" />

    <!-- The user's color palette data will be displayed in this RecyclerView -->
    <androidx.recyclerview.widget.RecyclerView
        android:elevation="20dp"
        android:outlineProvider="none"
        android:id="@+id/activityCanvas_colorPickerRecyclerView"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:orientation="horizontal"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintBottom_toBottomOf="@+id/activityCanvas_topView"
        app:layout_constraintEnd_toStartOf="@+id/activityCanvas_colorSwitcherView"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/activityCanvas_primaryFragmentHost"
        tools:listitem="@layout/color_picker_layout" />

    <!-- This FrameLayout is crucial when it comes to the calculation of the TransparentBackgroundView and PixelGridView -->
    <FrameLayout
        android:id="@+id/activityCanvas_distanceContainer"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/activityCanvas_tabLayout"
        app:layout_constraintEnd_toEndOf="@+id/activityCanvas_primaryFragmentHost"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/activityCanvas_topView" />

    <!-- This gives both views (the PixelGridView and TransparentBackgroundView) a nice drop shadow -->
    <com.google.android.material.card.MaterialCardView
        android:id="@+id/activityCanvas_cardView"
        style="@style/activityCanvas_canvasFragmentHostCardViewParent_style"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@+id/activityCanvas_tabLayout"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/activityCanvas_topView">
        <!-- At runtime, the width and height of the TransparentBackgroundView and PixelGridView will be calculated -->
       <com.therealbluepandabear.pixapencil.customviews.transparentbackgroundview.TransparentBackgroundView
            android:id="@+id/activityCanvas_transparentBackgroundView"
            android:layout_width="0dp"
            android:layout_height="0dp" />

        <com.therealbluepandabear.pixapencil.customviews.pixelgridview.PixelGridView
            android:id="@+id/activityCanvas_pixelGridView"
            android:layout_width="0dp"
            android:layout_height="0dp" />
    </com.google.android.material.card.MaterialCardView>

    <!-- The primary tab layout -->
    <com.google.android.material.tabs.TabLayout
        android:elevation="20dp"
        android:outlineProvider="none"
        android:id="@+id/activityCanvas_tabLayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:tabStripEnabled="false"
        app:layout_constraintBottom_toTopOf="@+id/activityCanvas_viewPager2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">
        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/activityCanvas_tab_tools_str" />

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/activityCanvas_tab_filters_str" />

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/activityCanvas_tab_color_palettes_str" />

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/activityCanvas_tab_brushes_str" />
    </com.google.android.material.tabs.TabLayout>

    <!-- This view allows move functionality -->
    <View
        android:elevation="20dp"
        android:outlineProvider="none"
        android:id="@+id/activityCanvas_moveView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@android:color/transparent"
        app:layout_constraintBottom_toBottomOf="@+id/activityCanvas_distanceContainer"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/activityCanvas_topView" />

    <!-- The tools, palettes, brushes, and filters fragment will be displayed inside this ViewPager -->
    <androidx.viewpager2.widget.ViewPager2
        android:elevation="20dp"
        android:outlineProvider="none"
        android:id="@+id/activityCanvas_viewPager2"
        android:layout_width="0dp"
        android:layout_height="110dp"
        app:layout_constraintBottom_toBottomOf="@+id/activityCanvas_primaryFragmentHost"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <!-- This CoordinatorLayout is responsible for ensuring that the app's snackbars can be swiped -->
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:elevation="20dp"
        android:outlineProvider="none"
        android:id="@+id/activityCanvas_coordinatorLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <!-- All of the full page fragments will be displayed in this fragment host -->
    <FrameLayout
        android:elevation="20dp"
        android:outlineProvider="none"
        android:id="@+id/activityCanvas_primaryFragmentHost"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

0度:

在此處輸入圖像描述

90度:

在此處輸入圖像描述

180度:

在此處輸入圖像描述

如您所見,旋轉 180 度時(原點為 0 度時)沒有陰影。

任何幫助將不勝感激為什么我會遇到這個問題,這不是主要問題,但它使我的應用程序的 UI 不一致。

注意:由於某種原因,我只在手機上遇到問題,而不是平板設備。

您在大多數項目上設置android:outlineProvider="none" ...而正在使用的投影可能具有錯誤的偏移坐標 - 您需要減去而不是添加偏移量。 提供的代碼太少,無法更准確地回答這個問題 - 但由於所述原因,陰影很可能只是隱藏在畫布下方。 我建議提供您自己的ViewOutlineProvider實現,然后通過 this 而不是none

您需要在android:layout_margin="16dp"的每一側設置總計(左、右、下和上)16dp 並設置app:cardElevation="4dp" ,它會起作用。

實際上,這是一件很奇怪的事情。 我試圖旋轉一個簡單的陰影視圖,它似乎在沒有任何邏輯原因的情況下在旋轉角度為 180/-180 時切斷了陰影。 我也嘗試與大綱提供者一起玩,但沒有。 所以這與 CardView 無關,而是來自在 View class 中繪制陰影的實現。

我搜索了一下,它已經直接報告給谷歌並修復了,但可能一些兼容庫仍然存在這個問題,這就是你面臨它的原因。

https://issuetracker.google.com/issues/173730323

https://issuetracker.google.com/issues/137454913

我可以建議您創建一個拐杖(是的,我知道,這不是解決方案)並留下評論。 如果你的旋轉大約是 -180/180,你可以用“-179.9/179.9”“標准化”它。 就用戶體驗而言,就漂亮的代碼而言,它是不可見的——嗯,但我在這里看不到任何其他方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM