Android 使用XML定义生成三角形形状?

Android 使用XML定义生成三角形形状?,android,xml,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=&

有没有一种方法可以在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>

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

<?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>

谢谢

我从未这样做过,但据我所知,您可以使用PathShape类:
我可以帮你不使用XML吗


简单地说

自定义布局(切片):

您的活动(示例):

工作示例:


另一个您可能感兴趣的绝对简单的
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;
}
在本文中,我描述了如何做到这一点。这是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>
并创建一个像


根据他的解决方案,如果您需要反向三角形,您可以使用:

<?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>




您可以获得更多选项。

在这种情况下,我肯定会实现视图:

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>

使用此实现将获得以下结果:

您可以使用

如果您的最小API低于21,Android Studio会在构建时自动为这些较低版本创建PNG位图(请参阅)。如果您使用支持库,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>
在模块的build.gradle中执行
defaultConfig

然后将(矢量xml)设置为可绘制,如下所示:

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

页面上的所有内容都记录得很好

从这项功能开始,我就一直在工作,在图标方面完全没有位图这也大大减少了APK大小。

请参见此处的答案:



对于那些想要直角三角形箭头的人,这里是:

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


步骤2:在布局的XML中,创建一个视图,并将其背景绑定到刚才在步骤1中创建的可绘制XML。在我的例子中,我将v_right_arrow绑定到视图的background属性

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

样本输出:


希望这有帮助,祝你好运

我的聚会可能会迟到,我遇到了同样的问题,谷歌给我指出了这个StackOverflow线程作为第一个结果

我尝试使用xml的方式添加三角形,并发现了三角形 通过xml实现形状的方法占用的空间比看起来的要大

请参见打开布局边界的屏幕截图

因此,我们制作了这个自定义视图类,它可以绘制以下任意类型的三角形:-

  • 指向上
  • 向下指向
  • 左指,
  • 右指
  • 以及

    您可以像这样简单地在xml布局中使用它

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

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

    您可以使用
    向量
    来制作这样的三角形

     <com.hiteshsahu.materialupvote.TriangleShapeView
                android:layout_width="50dp"
                android:layout_height="50dp"></com.hiteshsahu.materialupvote.TriangleShapeView>
    
    ic\u triangle\u right.xml

    <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>
    
    结果

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

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


    谷歌提供了一个等边三角形。
    选择VectorDrawable,使大小灵活。
    它作为插件集成到Android Studio中

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


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

    您可以使用以下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设计的整个逻辑在
    pathData
    中。考虑左上角为(0,0),根据您的要求设计布局。 检查答案。

    使用的解决方案,我制作了一个带有透明背景的定向向下的角度

    <?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>
    

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

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

    我尝试创建类似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>
    
    
    

    使用矢量绘图:

    <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>
    
    
    

    如果您不想破坏xml,我将在下面提供此customView。 请试一试


    /**
    *三角视图
    *
    *@author-Veer
    *@日期2020-09-03
    */
    类TriangalView@JVM重载构造函数(
    上下文:上下文,
    属性集?=null,
    defStyleAttr:Int=0
    ):视图(上下文、属性、defStyleAttr){
    私有变量三角形颜色:Int=0
    private var direction=direction.Bottom
    偷懒者的私人绘画{
    涂上油漆{
    Isatarias=真
    style=Paint.style.FILL
    颜色=t
    
    <?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>
    
    <View
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:background="@drawable/v_right_arrow">
    </View>
    
    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;
        }
    }
    
     <com.hiteshsahu.materialupvote.TriangleShapeView
                android:layout_width="50dp"
                android:layout_height="50dp"></com.hiteshsahu.materialupvote.TriangleShapeView>
    
    <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>
    
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:srcCompat="@drawable/ic_triangle_right"
        />
    
    <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>
    
     <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>
    
    <?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 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>
    
    <ImageView
        android:layout_width="10dp"
        android:layout_height="10dp"
        android:src="@drawable/ic_angle_down"
        />
    
    <rotate
        android:fromDegrees="135"
        android:pivotX="64.5%"
        android:pivotY="19%"
        android:toDegrees="135"
        >
    
    <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>
    
    <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>
    
    /**
     * 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>