注册

程序员浪漫起来 做一个心形layout

序言


最近浪漫心饱满,于是写了个心形控件。可以将一切内容约束成心形,并且支持两种心形,使用起来很简单,就当成FrameLayout就行了。
让一切都浪漫起来


效果


下面依次展示的是:



  1. 包裹ScrollView ,形状为桃心
  2. 包裹ScrollView,形状为圆心
  3. 包裹WebView,形状为圆心

在这里插入图片描述


代码


LoveLayout


主要代码就是下面的。

package com.example.myapplication;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Path;
import android.util.AttributeSet;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
* <pre>
* Created by zhuguohui
* Date: 2023/6/6
* Time: 10:26
* Desc:爱心Layout
* </pre>
*/
public class LoveLayout extends FrameLayout {

private Path path1;
private int heardType;

public LoveLayout(@NonNull Context context) {
super(context);
}

public LoveLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.LoveLayout);
heardType = array.getInt(R.styleable.LoveLayout_HeardType,0);
array.recycle();

}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if(heardType==0) {
getHeardPath();
}else{
getHeardPath2();
}
}

private void getHeardPath(){

int px = getMeasuredWidth() / 2;
int py = getMeasuredHeight() / 2;
path1=new Path();
path1.moveTo(px, py);
float rate=getMeasuredWidth()*1.0f/34;
// 根据心形函数画图
for (double i = 0; i < 2 * Math.PI; i += 0.001) {
float x = (float) (16 * Math.sin(i) * Math.sin(i) * Math.sin(i));
float y = (float) (13 * Math.cos(i) - 5 * Math.cos(2 * i) - 2 * Math.cos(3 * i) - Math.cos(4 * i));
x *= rate;
y *= rate;
x = px - x;
y = py - y;
path1.lineTo(x, y);
}
}

private void getHeardPath2(){
// f(x)=sqrt(1-(abs(x)-1)^2)
// h(x)=-2*sqrt(1-0.5*abs(x))
path1=getPathByMathFunction(x -> (float) Math.sqrt(1-Math.pow((Math.abs(x)-1),2)));
Path path2=getPathByMathFunction(x->(float) (-2* Math.sqrt(1-0.5*Math.abs(x))));
path1.moveTo(0,getMeasuredHeight()*1.0f/2);
path1.addPath(path2);
}

private interface MathFunction{
float call(float x);
}

private Path getPathByMathFunction(MathFunction function){
Path path=new Path();
path.moveTo(0,getMeasuredHeight()*1.0f/2);
int px = getMeasuredWidth() / 2;
int py = getMeasuredHeight() / 2;
float scale=getMeasuredWidth()*1.0f/4;
for(float i=-2;i<=2;i+=0.01){
float x=i;
float y= function.call(x);
x*=scale;
y*=scale;
x=px-x;
y=py-y;

path.lineTo(x,y);
}
return path;
}

@Override
protected void dispatchDraw(Canvas canvas) {
int save = canvas.save();
canvas.clipPath(path1);
super.dispatchDraw(canvas);
canvas.restoreToCount(save);
}
}


xml属性

<?xml version="1.0" encoding="utf-8"?>
<resources>


<declare-styleable name="LoveLayout">

<attr name="HeardType">
<!-- 桃心 -->
<enum name="PeachHeart" value="0" />
<!-- 圆一点的心 -->
<enum name="CircularHeart" value="1" />
</attr>
</declare-styleable>


</resources>

数学原理


圆心是按照以下公式实现的,桃心是网上找到的代码改的,没找到公司。
在这里插入图片描述


使用


很简单,当成FrameLayout包裹就行了。
在这里插入图片描述


作者:solo_99
链接:https://juejin.cn/post/7241447629874659365
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册