2024年Android最全Android FoldingLayout 折叠布局 原理及实现(一),2024年最新2024阿里Android高级面试题总结

【附】相关架构及资料

源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,和技术大牛一起讨论交流解决问题。

image

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

R.drawable.tanyan);

mMatrix = new Matrix();

mShadowPaint = new Paint();

mShadowPaint.setStyle(Style.FILL);

mShadowGradientShader = new LinearGradient(0, 0, 0.5f, 0,

Color.BLACK, Color.TRANSPARENT, TileMode.CLAMP);

mShadowPaint.setShader(mShadowGradientShader);

mShadowGradientMatrix = new Matrix();

mShadowGradientMatrix.setScale(mBitmap.getWidth(), 1);

mShadowGradientShader.setLocalMatrix(mShadowGradientMatrix);

mShadowPaint.setAlpha((int) (0.9*255));

}

@Override

protected void onDraw(Canvas canvas)

{

super.onDraw(canvas);

canvas.save();

float[] src = //…;

float[] dst = //…;

mMatrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1);

canvas.concat(mMatrix);

canvas.drawBitmap(mBitmap, 0, 0, null);

//绘制阴影 canvas.drawRect(0, 0, mBitmap.getWidth(), mBitmap.getHeight(),

mShadowPaint);

canvas.restore();

}

}

}

重点看mShadowPaint,mShadowGradientShader,mShadowGradientMatrix一个是画笔,我们为画笔设置了一个渐变的Shader,这个Shader的参数为

new LinearGradient(0, 0, 0.5f, 0,Color.BLACK, Color.TRANSPARENT, TileMode.CLAMP);

起点(0,0)、终点(0.5f,0);颜色从和BLACK到透明;模式为CLAMP,也就是拉伸最后一个像素。

这里你可能会问,这才为0.5个像素的区域设置了渐变,不对呀,恩,是的,继续看接下来我们使用了setLocalMatrix(mShadowGradientMatrix);,而这个

mShadowGradientMatrix将和坐标扩大了mBitmap.getWidth()倍,也就是说现在设置渐变的区域为(0.5f*mBitmap.getWidth(),0)半张图的大小,那么后半张图呢?

后半张应用CLAMP模式,拉伸的透明。

关于Shader、setLocalMatrix等用法也可以参考:Android BitmapShader 实战 实现圆形、圆角图片

4、初步实现折叠

========

了解了原理以及阴影的绘制以后,接下来要开始学习真正的去折叠了,我们的目标效果为:

妹子折叠成了8份,且阴影的范围为:每个沉下去夹缝的左右两侧,左侧黑色半透明遮盖,右侧短距离的黑色到透明阴影(大家可以仔细看)。

现在其实大家以及会将图片简单倾斜和添加阴影了,那么唯一的难点就是怎么将一张图分成很多快,我相信每块的折叠大家都会。

其实我们可以通过绘制该图多次,比如第一次绘制往下倾斜;第二次绘制网上倾斜;这样就和我们标题2的实现类似了,只需要利用setPolyToPoly。

那么绘制多次,每次显示肯定不是一整张图,比如第一次,我只想显示第一块,所以我们还需要clipRect的配合,说到这,应该以及揭秘了~~~

package com.zhy.sample.folderlayout;

import android.app.Activity;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.LinearGradient;

import android.graphics.Matrix;

import android.graphics.Paint;

import android.graphics.Paint.Style;

import android.graphics.Shader.TileMode;

import android.os.Bundle;

import android.view.View;

public class SimpleUseActivity extends Activity

{

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(new PolyToPolyView(this));

}

class PolyToPolyView extends View

{

private static final int NUM_OF_POINT = 8;

/**

  • 图片的折叠后的总宽度

*/

private int mTranslateDis;

/**

  • 折叠后的总宽度与原图宽度的比例

*/

private float mFactor = 0.8f;

/**

  • 折叠块的个数

*/

private int mNumOfFolds = 8;

private Matrix[] mMatrices = new Matrix[mNumOfFolds];

private Bitmap mBitmap;

/**

  • 绘制黑色透明区域

*/

private Paint mSolidPaint;

/**

  • 绘制阴影

*/

private Paint mShadowPaint;

private Matrix mShadowGradientMatrix;

private LinearGradient mShadowGradientShader;

/***

  • 原图每块的宽度

*/

private int mFlodWidth;

/**

  • 折叠时,每块的宽度

*/

private int mTranslateDisPerFlod;

public PolyToPolyView(Context context)

{

super(context);

mBitmap = BitmapFactory.decodeResource(getResources(),

R.drawable.tanyan);

//折叠后的总宽度

mTranslateDis = (int) (mBitmap.getWidth() * mFactor);

//原图每块的宽度

mFlodWidth = mBitmap.getWidth() / mNumOfFolds;

//折叠时,每块的宽度

mTranslateDisPerFlod = mTranslateDis / mNumOfFolds;

//初始化matrix

for (int i = 0; i < mNumOfFolds; i++)

{

mMatrices[i] = new Matrix();

}

mSolidPaint = new Paint();

int alpha = (int) (255 * mFactor * 0.8f) ;

mSolidPaint

.setColor(Color.argb((int) (alpha*0.8F), 0, 0, 0));

mShadowPaint = new Paint();

mShadowPaint.setStyle(Style.FILL);

mShadowGradientShader = new LinearGradient(0, 0, 0.5f, 0,

Color.BLACK, Color.TRANSPARENT, TileMode.CLAMP);

mShadowPaint.setShader(mShadowGradientShader);

mShadowGradientMatrix = new Matrix();

mShadowGradientMatrix.setScale(mFlodWidth, 1);

mShadowGradientShader.setLocalMatrix(mShadowGradientMatrix);

mShadowPaint.setAlpha(alpha);

//纵轴减小的那个高度,用勾股定理计算下

int depth = (int) Math.sqrt(mFlodWidth * mFlodWidth

  • mTranslateDisPerFlod * mTranslateDisPerFlod)/2;

//转换点

float[] src = new float[NUM_OF_POINT];

float[] dst = new float[NUM_OF_POINT];

/**

  • 原图的每一块,对应折叠后的每一块,方向为左上、右上、右下、左下,大家在纸上自己画下

*/

for (int i = 0; i < mNumOfFolds; i++)

{

src[0] = i * mFlodWidth;

src[1] = 0;

src[2] = src[0] + mFlodWidth;

src[3] = 0;

src[4] = src[2];

src[5] = mBitmap.getHeight();

src[6] = src[0];

src[7] = src[5];

boolean isEven = i % 2 == 0;

dst[0] = i * mTranslateDisPerFlod;

dst[1] = isEven ? 0 : depth;

dst[2] = dst[0] + mTranslateDisPerFlod;

dst[3] = isEven ? depth : 0;

dst[4] = dst[2];

dst[5] = isEven ? mBitmap.getHeight() - depth : mBitmap

.getHeight();

dst[6] = dst[0];

dst[7] = isEven ? mBitmap.getHeight() : mBitmap.getHeight()

  • depth;

//setPolyToPoly

mMatrices[i].setPolyToPoly(src, 0, dst, 0, src.length >> 1);

}

}

@Override

protected void onDraw(Canvas canvas)

{

super.onDraw(canvas);

//绘制mNumOfFolds次

for (int i = 0; i < mNumOfFolds; i++)

{

canvas.save();

//将matrix应用到canvas

canvas.concat(mMatrices[i]);

//控制显示的大小

canvas.clipRect(mFlodWidth * i, 0, mFlodWidth * i + mFlodWidth,

mBitmap.getHeight());

//绘制图片

canvas.drawBitmap(mBitmap, 0, 0, null);

//移动绘制阴影

canvas.translate(mFlodWidth * i, 0);

if (i % 2 == 0)

{

//绘制黑色遮盖

canvas.drawRect(0, 0, mFlodWidth, mBitmap.getHeight(),

mSolidPaint);

}else

{

//绘制阴影

canvas.drawRect(0, 0, mFlodWidth, mBitmap.getHeight(),

mShadowPaint);

}

canvas.restore();

}

}

}

}

简单讲解下,不去管绘制阴影的部分,其实折叠就是:

1、初始化转换点,这里注释说的很清楚,大家最好在纸上绘制下,标一下每个变量。

2、为matrix.setPolyToPoly

3、绘制时使用该matrix,且clipRect控制显示区域(这个区域也很简单,原图的第一块到最后一块),最好就是绘制bitmap了。

阴影这里大家可以换个明亮点的图片去看看~~

最后

我一直以来都有整理练习大厂面试题的习惯,有随时跳出舒服圈的准备,也许求职者已经很满意现在的工作,薪酬,觉得习惯而且安逸。

不过如果公司突然倒闭,或者部门被裁减,还能找到这样或者更好的工作吗?

我建议各位,多刷刷面试题,知道最新的技术,每三个月可以去面试一两家公司,因为你已经有不错的工作了,所以可以带着轻松的心态去面试,同时也可以增加面试的经验。

我可以将最近整理的一线互联网公司面试真题+解析分享给大家,大概花了三个月的时间整理2246页,帮助大家学习进步。

由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!以下是部分内容截图:

部分目录截图

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

,还能找到这样或者更好的工作吗?

我建议各位,多刷刷面试题,知道最新的技术,每三个月可以去面试一两家公司,因为你已经有不错的工作了,所以可以带着轻松的心态去面试,同时也可以增加面试的经验。

我可以将最近整理的一线互联网公司面试真题+解析分享给大家,大概花了三个月的时间整理2246页,帮助大家学习进步。

由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!以下是部分内容截图:

[外链图片转存中…(img-2prUbfqE-1715601013453)]

[外链图片转存中…(img-a1DQnUE8-1715601013453)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 12
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值