Programing

다중 그라데이션 모양

crosscheck 2020. 5. 22. 23:43
반응형

다중 그라데이션 모양


다음 이미지와 같은 모양을 만들고 싶습니다.

대체 텍스트

색상 1에서 색상 2 로의 상단 절반 그라디언트를 주목하지만 하단 3에서 색상 3에서 색상 4로 그라디언트하는 하단 절반이 있습니다. 단일 그라디언트로 모양을 만드는 방법을 알고 있지만 모양을 분할하는 방법을 잘 모르겠습니다 두 개의 반쪽과 두 개의 다른 그라디언트로 하나의 모양을 만듭니다.

어떤 아이디어?


나는 당신이 XML (적어도 안드로이드에서는 아님)로 이것을 할 수 있다고 생각하지 않지만, 여기게시 되어 큰 도움이 될만한 좋은 해결책을 찾았습니다 !

ShapeDrawable.ShaderFactory sf = new ShapeDrawable.ShaderFactory() {
    @Override
    public Shader resize(int width, int height) {
        LinearGradient lg = new LinearGradient(0, 0, width, height,
            new int[]{Color.GREEN, Color.GREEN, Color.WHITE, Color.WHITE},
            new float[]{0,0.5f,.55f,1}, Shader.TileMode.REPEAT);
        return lg;
    }
};

PaintDrawable p=new PaintDrawable();
p.setShape(new RectShape());
p.setShaderFactory(sf);

기본적으로 int 배열을 사용하면 여러 색상 정지 점을 선택할 수 있으며 다음 float 배열은 해당 정지 점이 배치되는 위치를 정의합니다 (0에서 1까지). 그런 다음 명시된대로 표준 Drawable로 사용할 수 있습니다.

편집 : 시나리오에서 이것을 사용하는 방법은 다음과 같습니다. XML로 정의 된 Button이 있다고 가정 해 봅시다.

<Button
    android:id="@+id/thebutton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Press Me!"
    />

그런 다음 onCreate () 메소드에 다음과 같은 것을 넣으십시오.

Button theButton = (Button)findViewById(R.id.thebutton);
ShapeDrawable.ShaderFactory sf = new ShapeDrawable.ShaderFactory() {
    @Override
    public Shader resize(int width, int height) {
        LinearGradient lg = new LinearGradient(0, 0, 0, theButton.getHeight(),
            new int[] { 
                Color.LIGHT_GREEN, 
                Color.WHITE, 
                Color.MID_GREEN, 
                Color.DARK_GREEN }, //substitute the correct colors for these
            new float[] {
                0, 0.45f, 0.55f, 1 },
            Shader.TileMode.REPEAT);
         return lg;
    }
};
PaintDrawable p = new PaintDrawable();
p.setShape(new RectShape());
p.setShaderFactory(sf);
theButton.setBackground((Drawable)p);

나는 현재 이것을 테스트 할 수 없다. 이것은 내 머리의 코드이지만 기본적으로 필요한 색상을 대체하거나 정지를 추가한다. 기본적으로 내 예에서는 연한 녹색으로 시작하고 중심보다 약간 전에 흰색으로 희미 해져 (가혹한 전환이 아닌 페이드를 제공하기 위해) 45 %에서 55 % 사이의 흰색에서 중간 녹색으로 페이드 인 중간 녹색에서 진한 녹색으로 55 %에서 끝까지. 이것은 모양과 똑같지 않을 수도 있지만 (지금은이 색상을 테스트 할 방법이 없습니다), 예제를 복제하도록이를 수정할 수 있습니다.

편집 : 또한 0, 0, 0, theButton.getHeight()그라디언트의 x0, y0, x1, y1 좌표를 나타냅니다. 따라서 기본적으로 x = 0 (왼쪽), y = 0 (위)에서 시작하여 x = 0으로 확장됩니다 (수직 그라디언트를 원하므로 왼쪽에서 오른쪽 각도가 필요하지 않습니다), y = 높이 버튼의. 따라서 그래디언트는 버튼 상단에서 버튼 하단까지 90도 각도로 진행됩니다.

편집 : 좋아, 그래서 작동하는 아이디어가 하나 더 있습니다. 현재는 XML로 작동하지만 Java의 모양에도 적용 할 수 있어야합니다. 그것은 복잡하고 하나의 모양으로 단순화 할 수있는 방법이 있다고 생각하지만 이것이 내가 지금 얻은 것입니다.

green_horizontal_gradient.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <corners
        android:radius="3dp"
        />
    <gradient
        android:angle="0"
        android:startColor="#FF63a34a"
        android:endColor="#FF477b36"
        android:type="linear"
        />    
</shape>

half_overlay.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <solid
        android:color="#40000000"
        />
</shape>

layer_list.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <item
        android:drawable="@drawable/green_horizontal_gradient"
        android:id="@+id/green_gradient"
        />
    <item
        android:drawable="@drawable/half_overlay"
        android:id="@+id/half_overlay"
        android:top="50dp"
        />
</layer-list>

test.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    >
    <TextView
        android:id="@+id/image_test"
        android:background="@drawable/layer_list"
        android:layout_width="fill_parent"
        android:layout_height="100dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:gravity="center"
        android:text="Layer List Drawable!"
        android:textColor="@android:color/white"
        android:textStyle="bold"
        android:textSize="26sp"     
        />
</RelativeLayout>

Okay, so basically I've created a shape gradient in XML for the horizontal green gradient, set at a 0 degree angle, going from the top area's left green color, to the right green color. Next, I made a shape rectangle with a half transparent gray. I'm pretty sure that could be inlined into the layer-list XML, obviating this extra file, but I'm not sure how. But okay, then the kind of hacky part comes in on the layer_list XML file. I put the green gradient as the bottom layer, then put the half overlay as the second layer, offset from the top by 50dp. Obviously you'd want this number to always be half of whatever your view size is, though, and not a fixed 50dp. I don't think you can use percentages, though. From there, I just inserted a TextView into my test.xml layout, using the layer_list.xml file as my background. I set the height to 100dp (twice the size of the offset of the overlay), resulting in the following:

대체 텍스트

타다!

한 번 더 편집 : 아이템으로 레이어 목록 드로어 블에 도형을 포함시킬 수 있다는 것을 깨달았습니다. 더 이상 3 개의 별도 XML 파일이 필요하지 않습니다! 다음과 같이 조합하여 동일한 결과를 얻을 수 있습니다.

layer_list.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <item>
        <shape
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:shape="rectangle"
            >
            <corners
                android:radius="3dp"
                />
            <gradient
                android:angle="0"
                android:startColor="#FF63a34a"
                android:endColor="#FF477b36"
                android:type="linear"
                />    
        </shape>
    </item>
    <item
        android:top="50dp" 
        >
        <shape
            android:shape="rectangle"
            >
            <solid
                android:color="#40000000"
                />
        </shape>            
    </item>
</layer-list>

이 방법으로 원하는만큼 항목을 레이어 할 수 있습니다! 나는 장난을 치며 Java를 통해 더 다양한 결과를 얻을 수 있는지 확인할 수 있습니다.

나는 이것이 마지막 편집이라고 생각합니다 ... : 좋아, 다음과 같이 Java를 통해 위치를 확실히 수정할 수 있습니다.

    TextView tv = (TextView)findViewById(R.id.image_test);
    LayerDrawable ld = (LayerDrawable)tv.getBackground();
    int topInset = tv.getHeight() / 2 ; //does not work!
    ld.setLayerInset(1, 0, topInset, 0, 0);
    tv.setBackgroundDrawable(ld);

하나! 이로 인해 TextView가 그려 질 때까지 TextView를 측정 할 수 없다는 또 다른 성가신 문제가 발생합니다. 아직 어떻게 수행 할 수 있는지 잘 모르겠지만 topInset에 숫자를 수동으로 삽입하면 작동합니다.

거짓말 하나 더 편집

Okay, found out how to manually update this layer drawable to match the height of the container, full description can be found here. This code should go in your onCreate() method:

final TextView tv = (TextView)findViewById(R.id.image_test);
        ViewTreeObserver vto = tv.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                LayerDrawable ld = (LayerDrawable)tv.getBackground();
                ld.setLayerInset(1, 0, tv.getHeight() / 2, 0, 0);
            }
        });

And I'm done! Whew! :)


You can layer gradient shapes in the xml using a layer-list. Imagine a button with the default state as below, where the second item is semi-transparent. It adds a sort of vignetting. (Please excuse the custom-defined colours.)

<!-- Normal state. -->
<item>
    <layer-list>
        <item>  
            <shape>
                <gradient 
                    android:startColor="@color/grey_light"
                    android:endColor="@color/grey_dark"
                    android:type="linear"
                    android:angle="270"
                    android:centerColor="@color/grey_mediumtodark" />
                <stroke
                    android:width="1dp"
                    android:color="@color/grey_dark" />
                <corners
                    android:radius="5dp" />
            </shape>
        </item>
        <item>  
            <shape>
                <gradient 
                    android:startColor="#00666666"
                    android:endColor="#77666666"
                    android:type="radial"
                    android:gradientRadius="200"
                    android:centerColor="#00666666"
                    android:centerX="0.5"
                    android:centerY="0" />
                <stroke
                    android:width="1dp"
                    android:color="@color/grey_dark" />
                <corners
                    android:radius="5dp" />
            </shape>
        </item>
    </layer-list>
</item>


You CAN do it using only xml shapes - just use layer-list AND negative padding like this:

    <layer-list>

        <item>
            <shape>
                <solid android:color="#ffffff" />

                <padding android:top="20dp" />
            </shape>
        </item>

        <item>
            <shape>
                <gradient android:endColor="#ffffff" android:startColor="#efefef" android:type="linear" android:angle="90" />

                <padding android:top="-20dp" />
            </shape>
        </item>

    </layer-list>

Have you tried to overlay one gradient with a nearly-transparent opacity for the highlight on top of another image with an opaque opacity for the green gradient?


이 방법을 사용하면 원하는 모든 것을 할 수 있습니다. 스택
과 같으 므로 어떤 항목이 먼저 또는 마지막에 오게 조심하십시오.

<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:right="50dp" android:start="10dp" android:left="10dp">
    <shape
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <corners android:radius="3dp" />
        <solid android:color="#012d08"/>
    </shape>
</item>
<item android:top="50dp">
    <shape android:shape="rectangle">
        <solid android:color="#7c4b4b" />
    </shape>
</item>
<item android:top="90dp" android:end="60dp">
    <shape android:shape="rectangle">
        <solid android:color="#e2cc2626" />
    </shape>
</item>
<item android:start="50dp" android:bottom="20dp" android:top="120dp">
    <shape android:shape="rectangle">
        <solid android:color="#360e0e" />
    </shape>
</item>

참고 URL : https://stackoverflow.com/questions/4381033/multi-gradient-shapes

반응형