MaterialShadows

介绍:

一个支持不规则形状的阴影效果库。

运行效果:

使用说明:

dependency

dependencies {
      compile 'com.sdsmdg.harjot:materialshadows:1.2.0'
}

MaterialShadowViewWrapper继承自 Relative Layout,MaterialShadowFrameLayoutWrapper继承自FrameLayout,根据个人喜好使用任意一个。

All the child views go through the same process of generating shadow as given below :

  1. First a bitmap is generated from the drawing cache of the view.

  2. The bitmap is traversed pixel by pixel to remove all transparent pixels and get a list of points corresponding to the actual outline of the content of the view.

  3. Since the points corresponding to outline may give a concave path, hence GrahamScan algorithm is used to generate a convex hull of the outline points.

  4. A path is created from the points of the resulting convex hull.

  5. This path is passed to a CustomViewOutlineProvider object that is later attached to the view itself.

  6. Hence we get a convex shadow for any type of view based on its content.

P.S. : All the calculations related to graham scan are done asynchronously by default. This behavior can be controlled by calculateAsync parameter. (Thanks Yaroslav!)

示例1(基本)

XML

<com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <ImageView
            android:layout_width="130dp"
            android:layout_height="130dp"
            android:elevation="5dp"
            android:src="@drawable/poly" />
</com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper>

Result

example_1.png

示例2(offset)

XML

<com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:shadowOffsetX="-15"
        app:shadowOffsetY="30">
        <ImageView
            android:layout_width="130dp"
            android:layout_height="130dp"
            android:elevation="10dp"
            android:src="@drawable/poly" />
</com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper>

效果

example_2.png

示例3(Shadow intensity)

xml

<com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:shadowOffsetX="-15"
        app:shadowOffsetY="30"
        app:shadowAlpha="0.9">
        <ImageView
            android:layout_width="130dp"
            android:layout_height="130dp"
            android:elevation="10dp"
            android:src="@drawable/poly" />
</com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper>

效果

example_3.png

示例4(Semi-transparent views)

xml

<com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:shadowOffsetX="-30"
        app:shadowOffsetY="30">
        <ImageView
            android:layout_width="130dp"
            android:layout_height="130dp"
            android:elevation="10dp"
            android:background="#55000000" />
</com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper>

效果

example_4.png

Using MaterialShadows with custom ViewGroups

因为 ShadowGenerator.java包括了产生阴影的所有相关代码,所以很容易把它应用到自定义的ViewGroup中:

public class CustomShadowWrapper extends CustomViewGroup {
      
      ShadowGenerator shadowGenerator;
      
      @Override
      protected void onLayout(boolean changed, int l, int t, int r, int b) {
          super.onLayout(changed, l, t, r, b);
          if (shadowGenerator == null) {
              shadowGenerator = new ShadowGenerator(this, offsetX, offsetY, shadowAlpha, shouldShowWhenAllReady, shouldCalculateAsync, shouldAnimateShadow, animationDuration);
          }
          shadowGenerator.generate();
      }
    
      @Override
      protected void onDetachedFromWindow() {
          super.onDetachedFromWindow();
          if (shadowGenerator != null) {
              shadowGenerator.releaseResources();
          }
      }
      
}

注 : 确保定义了ShadowGenerator需要的所有7个参数 offsetX, offsetY, shadowAlpha, shouldShowWhenAllReady, shouldCalculateAsync, shouldAnimateShadow, animationDuration。并处理参数值的变化。

假如某个参数发生了变化,比如OffsetX,在OffsetX的setter方法中添加如下代码:

public void setOffsetX(float offsetX) {
      this.offsetX = offsetX;
      if (shadowGenerator != null) {
            shadowGenerator.setOffsetX(offsetX);
      }
}

详细做法见 MaterialShadowViewWrapper

Documentation

XML attributeJava set methodsDescriptionDefault Value
shadowOffsetXsetOffsetX(...)Set the X-offset of the shadow0.0f
shadowOffsetYsetOffsetX(...)Set the Y-offset of the shadow0.0f
shadowAlphasetShadowAlpha(...)Set the value of shadow intensity (alpha)1.0f
calculateAsyncsetShouldCalculateAsync(...)Set the flag for async shadow calculations.true
showWhenAllReadysetShowShadowsWhenAllReady(...)Set the flag for showing all shadows after all calculations are overtrue
animateShadowsetShouldAnimateShadow(...)Set the flag for shadow animationtrue
animationDurationsetAnimationDuration(...)Set the value of shadow animation duration.300ms

限制

  1. 因为bitmap是按像素遍历的,对于大的view性能可能不是很好。因此这个库主要用于小型的view。

  2. 目前只对MaterialShadowViewWrapper的直接子view生成阴影。因此如果一个view是在Linear Layout或者其它的 view group中,需要把每个view都用MaterialShadowViewWrapper或者MaterialShadowFrameLayoutWrapper包裹一遍,或者你也可以自定义view group 。

  3. MaterialShadowViewWrapper或者自定义的 view group wrapper 中的子view都使用相同的阴影,所以如果你要为每个子view单独使用阴影,必需把每个子view都放在MaterialShadowViewWrapper中。

已下载
0