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

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

谢谢

180399 次浏览

我从来没有这样做过,但是根据我的理解,您可以使用 PathShape 类: Http://developer.android.com/reference/android/graphics/drawable/shapes/pathshape.html

我可以帮助你使用 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;
}

这篇文章中我描述了如何做到这一点,下面是 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>

如果有什么不清楚或者你需要解释它是如何构建的,请参考我的文章。它是旋转一个切割矩形:)这是非常聪明和良好的工作解决方案。

编辑: 要创建指向—— > 的箭头,请使用:

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

并创建一个指向 < —— use:

android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="87%"
android:pivotY="140%" >
  <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>

解决方案适合我,根据他的解决方案,如果你需要倒三角形,你可以使用这个:

<?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>
<?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>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="▼"/>

你可以得到 给你更多的选择。

在这种情况下,我肯定会采取以下做法:

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

你可以使用 矢量绘制件矢量绘制件

如果您的最小 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>

将其添加到布局中,并记住如果旋转三角形,则设置 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

通过设置 Viewslay _ width/outs _ height 属性来更改三角形的大小(宽度/高度)。这样,你也可以得到一个等边三角形,如果你做的数学正确。

更新资料25.11.2017

如果您使用支持库,您可以使用实际的矢量(而不是位图创建) ,最早可以追溯到 API 7 。简单地说:

vectorDrawables.useSupportLibrary = true

在模块的 build 中做 defaultConfig

然后像下面这样设置(向量 xml)可绘制性:

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

矢量资产工作室页面上,所有内容都被很好地记录下来。

自从这个功能以来,我一直在工作完全没有位图的图标

点击这里查看答案: 没有图像的自定义箭头: 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

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

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

<?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 并将其背景绑定到刚才在 步骤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

希望这个有用,祝你好运!

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

我尝试用 xml 的方法来添加三角形,并找出了一个问题,即三角形 形状通过 xml 方法占用的空间比看起来要多。

见屏幕截图与布局边界

enter image description here

因此最终创建了这个自定义视图类,它可以绘制以下任何类型的三角形:-

  1. 指向上方
  2. 往下指
  3. 左转 &
  4. 正确的指向

阿萨

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 方法的问题所在。我希望它能帮助某人。

你可以用 vector来做这样的三角形

Ic _ angle _ 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>

那就好好利用

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

改变颜色和方向,使用 android:tintandroid: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
/>

结果

enter image description here

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

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

enter image description here

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

谷歌提供了一个正三角形的 给你
选择 VectorDrawable,以便大小灵活。
它作为插件集成到 Android Studio 中。

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

一旦你有了 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) ,并根据您的需求设计布局。 检查 这个应答。

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

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

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

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>

使用矢量绘制:

<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

如果您不想破解 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>