Android翻页效果原理实现之翻页的尝试

尊重原创转载请注明:From AigeStudio()Power by Aige 侵权必究!

炮兵

镇楼

在《自定义控件其实很简单》系列的前半部分中我们用了整整六节近两万字两百多张配图讲了Android图形的绘制,虽然篇幅很巨大但仍然只是图形绘制的冰山一角,旨在领大家入门,至于修行成果就看各位的了……那么这个些列主要是通过前面学习到的一些方法来尝试完成一个翻页的效果。

对于我个人来说,我是不太建议大家在没自己去尝试前看本文的,因为你看了别人的思路就会有个惯性思维朝着别人的思路去靠,实际上如果你自己尝试去分析去做的话不见得做不出来,甚至可能方法更简捷效率更高。分析这个效果的时候我还找妹子要了个新的笔记本翻了两三个小时,后来又在PS里模拟了一下然后通过绘图计算最终才有了一个简短的思路。

翻页虽然几乎每个人都试过,除非你没看过书……没碰过本子……甚至没碰过纸……一个看似简单的动作其实隐藏了巨量的信息,如果我们要把翻页的过程模拟得真实,涉及面会相当广,这里我假定我们所做的翻页效果类似于课本翻页,从右下角掀开纸张翻至左边,而我们的控件就假定为课本的右边部分而左边部分呢在我们控件左侧外看不到,那么控件的左端即可看成我们课本的装订线,这样的假定我们可以简化问题,如之前我所说,控件必定都是不完美的,如果存在完美的控件就不需要我们Custom了~那么这个控件实现的是一个怎么样的效果呢?效果很简单,往控件中传入多张图片,我们以翻页的形式依次展示这些图片。整个翻页的原理都是想通的,虽然这个效果我模拟得很简单,但是你完全可以照我的思路定义ViewGroup或者ValueAnimation等等……

为了进一步简化问题,我们将整个翻页效果的实现分为四部分,第一部分为翻页的尝试实现,第二部分呢则是折线翻页的实现,第三部分我们尝试引入曲线翻页,第四部分则为一些后续效果的处理以及效率的优化,如果有必要还会增加一些章节继续完善效果。这样我们的流程就很清晰了,这一节我们首先来尝试实现翻页,如果大家能哪个本子或者书来跟着我的思路走就更好了,本来是打算拍些Photo作为展示的,但是我发现现实的翻页不好控制,算了,一些理论上的东西只好靠各位自行动手+脑补了。

首先,我们要进行一些约定,上面说到我们模拟的翻页效果是以控件左侧为纸张装订线使其能够实现从右下角翻开的效果,这是约定之一,其次,我们规定忽略掀起部分相对于本页的弧线使之始终与本页平行,再次规定视点与光源方向均位于纸张正上方并且光源为单光源聚光灯光锥刚好罩住纸张,这些约定不理解不要紧,在涉及到的时候我会具体说明。

我们知道View并非像ViewGroup那样是个容器可以容纳其他的控件,那么要将一些图片依次“放入”View中并依次呈现该如何办呢?通过前面对Canvas的学习,我们可以尝试使用Canvas的“图层”功能来实现这一效果,将Bitmap依次至于不同的“图层”再通过Canvas的clipXXX方法裁剪呈现不同Bitmap,理论上是可行的,那实际如何呢?我们来试试,新建一个View的子类PageCurlView:

public class PageTurnView extends View {private List<Bitmap> mBitmaps;// 位图数据列表public PageTurnView(Context context, AttributeSet attrs) {super(context, attrs);}}同样,PageCurlView是与数据有关的,我们对外提供一个方法来为PageCurlView设置数据:

/** * 设置位图数据 * * @param mBitmaps *位图数据列表 */public synchronized void setBitmaps(List<Bitmap> mBitmaps) {/* * 如果数据为空则抛出异常 */if (null == mBitmaps || mBitmaps.size() == 0)throw new IllegalArgumentException("no bitmap to display");/* * 如果数据长度小于2则GG思密达 */if (mBitmaps.size() < 2)throw new IllegalArgumentException("fuck you and fuck to use imageview");this.mBitmaps = mBitmaps;invalidate();}这里要注意,如果图片小于两张,那就没必要去做翻页效果了,当然你也可以将其绘制出来然后在用户实行“翻页”的时候提示“已是最后一页”也可以,这里我就直接不允许图片张数小于2张了。

在《自定义控件其实很简单5/12》中我们自定义了一个折线视图,在该例中我们为PolylineView设置了一个初始化数据,即当用户没有设置数据时默认显示了一组随机值数据。那在这里呢我不再做初始化数据而是当绘制时如果数据为空那么我们就显示一组文本信息提示用户设置数据:

/** * 默认显示 * * @param canvas *Canvas对象 */private void defaultDisplay(Canvas canvas) {// 绘制底色canvas.drawColor(Color.WHITE);// 绘制标题文本mTextPaint.setTextSize(mTextSizeLarger);mTextPaint.setColor(Color.RED);canvas.drawText("FBI WARNING", mViewWidth / 2, mViewHeight / 4, mTextPaint);// 绘制提示文本mTextPaint.setTextSize(mTextSizeNormal);mTextPaint.setColor(Color.BLACK);canvas.drawText("Please set data use setBitmaps method", mViewWidth / 2, mViewHeight / 3, mTextPaint);}

如果没有设置数据,那么PageCurlView的默认显示效果如下:

如果有数据,那么我们在绘制这些位图之前要对其大小进行调整,这里我就直接将位图的大小矫正与控件一致,,当然实际应用当中你可以根据比例来缩放图片使其保持宽高比,这里我就直接舍弃宽高比了:

/** * 初始化位图数据 * 缩放位图尺寸与屏幕匹配 */private void initBitmaps() {List<Bitmap> temp = new ArrayList<Bitmap>();for (int i = 0; i < mBitmaps.size(); i++) {Bitmap bitmap = Bitmap.createScaledBitmap(mBitmaps.get(i), mViewWidth, mViewHeight, true);temp.add(bitmap);}mBitmaps = temp;}那么数据有了,我们尝试将其绘制出来看看:

在这个阳光明媚的三月,我从我单薄的青春里打马而过,

Android翻页效果原理实现之翻页的尝试

相关文章:

你感兴趣的文章:

标签云: