使用xml定义制作三角形?

时间:2010-03-25 16:54:20

标签: android xml

有没有办法在xml文件中指定三角形?

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="triangle">
  <stroke android:width="1dip" android:color="#FFF" />
  <solid android:color="#FFF" />
</shape>

我们可以用路径形状做什么吗?我只需要一个等边三角形。

由于

20 个答案:

答案 0 :(得分:156)

this post我描述了如何做到这一点。这是XML定义三角形:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <rotate
            android:fromDegrees="45"
            android:toDegrees="45"
            android:pivotX="-40%"
            android:pivotY="87%" >
            <shape
                android:shape="rectangle" >
                <stroke android:color="@color/transparent" android:width="10dp"/>
                <solid
                    android:color="@color/your_color_here" />
            </shape>
        </rotate>
    </item>
</layer-list>

如果某些内容不清楚或您需要解释如何构建,请参阅我的帖子。它旋转了一个切口矩形:)这是非常聪明和良好的工作解决方案。

编辑: 创建一个箭头指向 - &gt;使用方法:

...
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="13%"
android:pivotY="-40%" >
...

创建一个指向&lt; - use:

的箭头
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="87%"
android:pivotY="140%" >

答案 1 :(得分:78)

<TextView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="▼"/>

您可以获得here个更多选项。

答案 2 :(得分:49)

您可以使用<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> <path android:pathData="M0,12l0,12 11.5,-5.7c6.3,-3.2 11.5,-6 11.5,-6.3 0,-0.3 -5.2,-3.1 -11.5,-6.3l-11.5,-5.7 0,12z" android:strokeColor="#00000000" android:fillColor="#000000"/> </vector> 制作这样的三角形

<强> ic_triangle_right.xml

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@drawable/ic_triangle_right"
    />

然后像

一样使用它
android:tint

要更改颜色和方向,请使用android:rotation<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" app:srcCompat="@drawable/ic_triangle_right" android:rotation="180" // change direction android:tint="#00f" // change color />

<vector 
        android:width="10dp"
        android:height="24dp"
        >
       ...
</vector>

结果

enter image description here

要更改矢量的形状,可以更改矢量的宽度/高度。示例将宽度更改为10dp

{{1}}

enter image description here

答案 3 :(得分:39)

我会定义在这种情况下实现View:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;

public class TriangleShapeView extends View {

    public TriangleShapeView(Context context) {
        super(context);
    }

    public TriangleShapeView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public TriangleShapeView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int w = getWidth() / 2;

        Path path = new Path();
        path.moveTo( w, 0);
        path.lineTo( 2 * w , 0);
        path.lineTo( 2 * w , w);
        path.lineTo( w , 0);
        path.close();

        Paint p = new Paint();
        p.setColor( Color.RED );

        canvas.drawPath(path, p);
    }
}

在布局中使用它,如下所示:

<TriangleShapeView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff487fff">
</TriangleShapeView>

使用此实现将为您提供以下结果:

enter image description here

答案 4 :(得分:39)

您可以使用vector drawables

如果您的最低API低于21,Android Studio会在构建时为这些较低版本自动创建PNG位图(请参阅Vector Asset Studio)。如果您使用支持库,Android甚至可以管理“真正的向量”到API 7(更多内容在此帖子的更新底部)。

红色向上指向的三角形将是:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="100dp"
    android:width="100dp"
    android:viewportHeight="100"
    android:viewportWidth="100" >
    <group
        android:name="triableGroup">
        <path
            android:name="triangle"
            android:fillColor="#FF0000"
            android:pathData="m 50,0 l 50,100 -100,0 z" />
    </group>
</vector>

将它添加到您的布局中,如果旋转三角形,请记得设置clipChildren =“false”。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false">

    <ImageView
        android:layout_width="130dp"
        android:layout_height="100dp"
        android:rotation="0"
        android:layout_centerInParent="true"
        android:background="@drawable/triangle"/>

</RelativeLayout>

enter image description here

通过设置Views layout_width / layout_height属性来更改三角形的大小(宽度/高度)。这样,如果你的数学运算正确,你也可以得到一个eqilateral triagle。

更新25.11.2017

如果您使用支持库,您可以使用真实的向量(而不是创建位图),这可以追溯到API 7 。只需添加:

vectorDrawables.useSupportLibrary = true

在您的模块的build.gradle中执行defaultConfig

然后将(vector xml)drawable设置为:

<ImageView
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    app:srcCompat="@drawable/triangle" />

Vector Asset Studio页面上的所有内容都记录得非常好。

自从这个功能以来,我一直在完全没有图标方面的位图。 这也会大大降低APK的大小。

答案 5 :(得分:38)

solution of Jacek Milewski对我有用,根据他的解决方案,如果你需要和倒三角形,你可以使用它:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <rotate
            android:fromDegrees="45"
            android:toDegrees="45"
            android:pivotX="135%" 
            android:pivotY="15%">
            <shape android:shape="rectangle">    
                <solid android:color="@color/aquamarine" />
            </shape>
        </rotate>
    </item>
</layer-list>

答案 6 :(得分:18)

请在此处查看答案: Custom arrows without image: Android

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="32dp"
        android:height="24dp"
        android:viewportWidth="32.0"
        android:viewportHeight="24.0">
    <path android:fillColor="#e4e4e8"
          android:pathData="M0 0 h32 l-16 24 Z"/>
</vector>

arrow

答案 7 :(得分:11)

我可以帮助您不使用使用XML吗?


简单地说,

自定义布局(切片):

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.View;

public class Slice extends View {

    Paint mPaint;

    Path mPath;

    public enum Direction {
        NORTH, SOUTH, EAST, WEST
    }

    public Slice(Context context) {
        super(context);
        create();
    }

    public Slice(Context context, AttributeSet attrs) {
        super(context, attrs);
        create();
    }

    public void setColor(int color) {
        mPaint.setColor(color);
        invalidate();
    }

    private void create() {
        mPaint = new Paint();
        mPaint.setStyle(Style.FILL);
        mPaint.setColor(Color.RED);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        mPath = calculate(Direction.SOUTH);
        canvas.drawPath(mPath, mPaint);
    }

    private Path calculate(Direction direction) {
        Point p1 = new Point();
        p1.x = 0;
        p1.y = 0;

        Point p2 = null, p3 = null;

        int width = getWidth();

        if (direction == Direction.NORTH) {
            p2 = new Point(p1.x + width, p1.y);
            p3 = new Point(p1.x + (width / 2), p1.y - width);
        } else if (direction == Direction.SOUTH) {
            p2 = new Point(p1.x + width, p1.y);
            p3 = new Point(p1.x + (width / 2), p1.y + width);
        } else if (direction == Direction.EAST) {
            p2 = new Point(p1.x, p1.y + width);
            p3 = new Point(p1.x - width, p1.y + (width / 2));
        } else if (direction == Direction.WEST) {
            p2 = new Point(p1.x, p1.y + width);
            p3 = new Point(p1.x + width, p1.y + (width / 2));
        }

        Path path = new Path();
        path.moveTo(p1.x, p1.y);
        path.lineTo(p2.x, p2.y);
        path.lineTo(p3.x, p3.y);

        return path;
    }
}

您的活动(示例):

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;

public class Layout extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Slice mySlice = new Slice(getApplicationContext());
        mySlice.setBackgroundColor(Color.WHITE);
        setContentView(mySlice, new LinearLayout.LayoutParams(
                LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
    }
}

工作示例:

enter image description here


您可能感兴趣的另一个非常简单的Calculate函数..

private Path Calculate(Point A, Point B, Point C) {
    Path Pencil = new Path();
    Pencil.moveTo(A.x, A.y);
    Pencil.lineTo(B.x, B.y);
    Pencil.lineTo(C.x, C.y);
    return Pencil;
}

答案 8 :(得分:6)

对于那些想要一个直角三角箭头的人,请点击这里:

步骤1:创建可绘制的XML文件,将以下XML内容复制并粘贴到可绘制的XML中。 (请注意,您可以使用任何名称作为可绘制的XML文件。对于我的情况,我将其命名为&#34; v_right_arrow&#34;)

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item >
        <rotate
            android:fromDegrees="45"
            android:toDegrees="-45"
            android:pivotX="15%"
            android:pivotY="-36%" >
            <shape
                android:shape="rectangle"  >
                <stroke android:color="@android:color/transparent" android:width="1dp"/>
                <solid
                    android:color="#000000"  />
            </shape>
        </rotate>
    </item>
</layer-list>

第2步:在您的布局的XML中,创建一个View并将其背景绑定到您刚刚在 STEP 1 中创建的可绘制XML。对于我的情况,我将v_right_arrow绑定到我的View的背景属性。

<View
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:background="@drawable/v_right_arrow">
</View>

示例输出:

enter image description here

希望这有帮助,祝你好运!

答案 9 :(得分:4)

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <rotate
            android:fromDegrees="45"
            android:toDegrees="45"
            android:pivotX="-40%"
            android:pivotY="87%" >
            <shape
                android:shape="rectangle" >
                <stroke android:color="@android:color/transparent" android:width="0dp"/>
                <solid
                    android:color="#fff" />
            </shape>
        </rotate>
    </item>
</layer-list>

答案 10 :(得分:4)

 <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <rotate
                android:fromDegrees="45"
                android:pivotX="135%"
                android:pivotY="1%"
                android:toDegrees="45">
                <shape android:shape="rectangle">
                    <stroke
                        android:width="-60dp"
                        android:color="@android:color/transparent" />
                    <solid android:color="@color/orange" />
                </shape>
            </rotate>
        </item>
    </layer-list>

答案 11 :(得分:3)

我从未这样做过,但据我所知,你可以使用PathShape类: http://developer.android.com/reference/android/graphics/drawable/shapes/PathShape.html

答案 12 :(得分:3)

我迟到了,我遇到了同样的问题,谷歌把我作为第一个结果指向了这个StackOverflow线程。

  

我尝试使用xml方式添加三角形并找出三角形的问题   通过xml方法的形状占用的空间比它看起来要多。

查看

上的布局范围的屏幕截图

enter image description here

最终制作了这个自定义视图类,它可以绘制以下任何类型的Triangle: -

  1. 向上指着
  2. 向下指着
  3. 左指点&amp;
  4. 右指点
  5. ASAS

    package com.hiteshsahu.materialupvotewidget;    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.support.annotation.NonNull;
    import android.util.AttributeSet;
    import android.view.View;
    
    public class TriangleShapeView extends View {
    
        private int colorCode = Color.DKGRAY;
    
        public int getColorCode() {
            return colorCode;
        }
    
        public void setColorCode(int colorCode) {
            this.colorCode = colorCode;
        }
    
        public TriangleShapeView(Context context) {
            super(context);
            if (isInEditMode())
                return;
        }
    
        public TriangleShapeView(Context context, AttributeSet attrs) {
            super(context, attrs);
            if (isInEditMode())
                return;
        }
    
        public TriangleShapeView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    
            if (isInEditMode())
                return;
        }
    
    
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            int w = getWidth() / 2;
            int h = getHeight() / 2;
    
            //Choose what type of triangle you want here
            Path path = getLeftTriangle(w, h);
    
            path.close();
            Paint p = new Paint();
            p.setColor(colorCode);
            p.setAntiAlias(true);
    
            canvas.drawPath(path, p);
        }
    
        @NonNull
        /**
         * Return Path for down facing triangle
         */
        private Path getInvertedTriangle(int w, int h) {
            Path path = new Path();
            path.moveTo(0, 0);
            path.lineTo(w, 2 * h);
            path.lineTo(2 * w, 0);
            path.lineTo(0, 0);
            return path;
        }
    
        @NonNull
        /**
         * Return Path for Up facing triangle
         */
        private Path getUpTriangle(int w, int h) {
            Path path = new Path();
            path.moveTo(0, 2 * h);
            path.lineTo(w, 0);
            path.lineTo(2 * w, 2 * h);
            path.lineTo(0, 2 * h);
            return path;
        }
    
        @NonNull
        /**
         * Return Path for Right pointing triangle
         */
        private Path getRightTriangle(int w, int h) {
            Path path = new Path();
            path.moveTo(0, 0);
            path.lineTo(2 * w, h);
            path.lineTo(0, 2 * h);
            path.lineTo(0, 0);
            return path;
        }
    
        @NonNull
        /**
         * Return Path for Left pointing triangle
         */
        private Path getLeftTriangle(int w, int h) {
            Path path = new Path();
            path.moveTo(2 * w, 0);
            path.lineTo(0, h);
            path.lineTo(2 * w, 2 * h);
            path.lineTo(2 * w, 0);
            return path;
        }
    }
    

    您可以在xml布局中使用它,就像这样

     <com.hiteshsahu.materialupvote.TriangleShapeView
                android:layout_width="50dp"
                android:layout_height="50dp"></com.hiteshsahu.materialupvote.TriangleShapeView>
    

    我知道OP需要xml解决方案中的解决方案,但正如我指出xml方法的问题。我希望它可以帮助某人。

答案 13 :(得分:3)

您可以使用以下xml在背景中添加以下三角形

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="100dp"
    android:width="100dp"
    android:viewportHeight="100"
    android:viewportWidth="100" >
    <group
        android:name="triableGroup">
        <path
            android:name="triangle"
            android:fillColor="#848af8"
            android:pathData="M 0,20 L 0,0 L 100,0 L 100,20 L 54,55  l -1,0.6  l -1,0.4  l -1,0.2  l -1,0   l -1,-0  l -1,-0.2  l -1,-0.4  l -1,-0.6    L 46,55   L 0,20 -100,-100 Z" />
    </group>
</vector>

自定义xml设计的整个逻辑是在路径数据中。考虑左上角为(0,0)并根据需要设计布局。 检查this答案。

答案 14 :(得分:2)

使用矢量可绘制:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
   android:width="24dp"
   android:height="24dp"
   android:viewportWidth="24.0"
   android:viewportHeight="24.0">
   <path
        android:pathData="M0,0 L24,0 L0,24 z"
        android:strokeColor="@color/color"
        android:fillColor="@color/color"/>
</vector>

enter image description here

答案 15 :(得分:0)

  <LinearLayout
        android:id="@+id/ly_fill_color_shape"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="center"
        android:background="@drawable/shape_triangle"
        android:gravity="center"
        android:orientation="horizontal" >
    </LinearLayout>

<item>
    <rotate
        android:fromDegrees="45"
        android:pivotX="-15%"
        android:pivotY="77%"
        android:toDegrees="45" >
        <shape android:shape="rectangle" >
            <stroke
                android:width="2dp"
                android:color="@color/black_color" />

            <solid android:color="@color/white" />

            <padding android:left="1dp" />
        </shape>
    </rotate>
</item>
<item android:top="200dp">
    <shape android:shape="line" >
        <stroke
            android:width="1dp"
            android:color="@color/black_color" />

        <solid android:color="@color/white" /> 
    </shape>
</item>

答案 16 :(得分:0)

Google提供了等边三角形here 选择VectorDrawable,使尺寸灵活 它&#39;作为插件集成到Android Studio中。

如果您有SVG图像,则可以使用this将其转换为VectorDrawable。

一旦你有了VectorDrawable,就像其他人提到的那样,改变它的颜色和旋转很容易。

答案 17 :(得分:0)

使用Jacek Milewski的解决方案,我确定了一个具有透明背景的向下倾斜角度。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <rotate
            android:fromDegrees="135"
            android:pivotX="65%"
            android:pivotY="20%"
            android:toDegrees="135"
            >
            <shape android:shape="rectangle">
                <stroke
                    android:width="1dp"
                    android:color="@color/blue"
                    />
                <solid android:color="@color/transparent" />
            </shape>
        </rotate>
    </item>
</layer-list>

您可以更改android:pivotXandroid:pivotY来改变角度。

用法:

<ImageView
    android:layout_width="10dp"
    android:layout_height="10dp"
    android:src="@drawable/ic_angle_down"
    />

enter image description here

参数取决于图像的大小。例如,如果ImageView的大小为100dp * 80dp,则应使用以下常量:

<rotate
    android:fromDegrees="135"
    android:pivotX="64.5%"
    android:pivotY="19%"
    android:toDegrees="135"
    >

enter image description here

答案 18 :(得分:0)

我尝试创建类似于android导航栏的后退按钮的三角形图像,但是我没有找到任何解决方案。

现在,我自己找到了解决方案,并希望与大家分享。

triangle navigation bar android

在下面使用xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:bottom="20dp"
    android:left="480dp"
    android:right="60dp"
    android:top="20dp">
    <shape>
        <size android:width="60dp" />
        <corners android:radius="80dp"/>
        <solid android:color="#AAA" />
    </shape>
</item>
<item
    android:bottom="480dp"
    android:right="70dp"
    android:top="20dp">
    <rotate
        android:fromDegrees="-28"
        android:pivotX="96%"
        android:pivotY="50%"
        android:toDegrees="-20">
        <shape>
            <corners android:radius="80dp"/>
            <size android:height="60dp" />
            <solid android:color="#AAA" />
        </shape>
    </rotate>
</item>

<item
    android:bottom="20dp"
    android:right="70dp"
    android:top="480dp">
    <rotate
        android:fromDegrees="28"
        android:pivotX="96%"
        android:pivotY="50%"
        android:toDegrees="-20">
        <shape>
            <corners android:radius="80dp"/>
            <size android:height="60dp" />
            <solid android:color="#AAA" />
        </shape>
    </rotate>
</item>

答案 19 :(得分:0)

如果您不想破解xml,请在下面提供此customView。 请尝试一下。


/**
 * TriangleView
 *
 * @author Veer
 * @date 2020-09-03
 */
class TriangleView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    private var triangleColor: Int = 0
    private var direction = Direction.Bottom

    private val paint by lazy {
        Paint().apply {
            isAntiAlias = true
            style = Paint.Style.FILL
            color = triangleColor
        }
    }

    init {
        initStyle(context, attrs, defStyleAttr)
    }

    private fun initStyle(
        context: Context,
        attrs: AttributeSet?,
        defStyleAttr: Int
    ) {
        val ta = context.obtainStyledAttributes(attrs, R.styleable.TriangleView, defStyleAttr, 0)
        with(ta) {
            triangleColor =
                getColor(R.styleable.TriangleView_triangle_background, Color.parseColor("#000000"))

            val directionValue =
                getInt(R.styleable.TriangleView_triangle_direction, Direction.Bottom.value)
            direction = when (directionValue) {
                Direction.Top.value -> Direction.Top
                Direction.Bottom.value -> Direction.Bottom
                Direction.Left.value -> Direction.Left
                Direction.Right.value -> Direction.Right
                else -> Direction.Bottom
            }

            recycle()
        }
    }

    override fun onDraw(canvas: Canvas) {
        calculatePath(direction).let {
            canvas.drawPath(it, paint)
        }
    }

    private fun calculatePath(direction: Direction): Path {
        var p1: Point? = null
        var p2: Point? = null
        var p3: Point? = null

        val width = width
        val height = height

        when (direction) {
            Direction.Top -> {
                p1 = Point(0, height)
                p2 = Point(width / 2, 0)
                p3 = Point(width, height)
            }
            Direction.Bottom -> {
                p1 = Point(0, 0)
                p2 = Point(width / 2, height)
                p3 = Point(width, 0)
            }
            Direction.Left -> {
                p1 = Point(width, 0)
                p2 = Point(0, height / 2)
                p3 = Point(width, height)
            }
            Direction.Right -> {
                p1 = Point(0, 0)
                p2 = Point(width, height / 2)
                p3 = Point(0, height)
            }
        }

        val path = Path()
        path.moveTo(p1.x.toFloat(), p1.y.toFloat())
        path.lineTo(p2.x.toFloat(), p2.y.toFloat())
        path.lineTo(p3.x.toFloat(), p3.y.toFloat())
        return path
    }

    private enum class Direction(val value: Int) {
        Top(0),
        Bottom(1),
        Left(2),
        Right(3)
    }
}

<declare-styleable name="TriangleView">
    <attr name="triangle_direction" format="enum">
        <enum name="top" value="0" />
        <enum name="bottom" value="1" />
        <enum name="left" value="2" />
        <enum name="right" value="3" />
    </attr>
    <attr name="triangle_background" format="reference|color" />
</declare-styleable>