Android 不规则图像填充 小玩着色游戏

                       
 

转载请标明出处:
  http://blog.csdn.net/lmj623565791/article/details/45788433
  本文出自:【张鸿洋的博客】

一、概述

近期群里偶然看到一哥们在群里聊不规则图像填充什么四联通、八联通什么的,就本身好学务实的态度去查阅了相关资料。对于这类着色的资料,最好的就是去搜索些相关app,根据我的观察呢,不规则图像填充在着色游戏里面应用居多,不过大致可以分为两种:

  • 基于层的的填充
  • 基于边界的填充

那么针对上述两种,我们会通过两篇博文来讲解,本篇就是叙述基于层的填充方式,那么什么基于层的填充方式呢?其实就是一张图实际上是由多个层组成的,每个层显示部分图像(无图像部分为透明),多层叠加后形成一张完整的图案,图层间是叠加的关系,类似下图。

相信大家如果学过PS,对上述肯定再了解不过了。比如你要绘制一个天空,你可以最底层去绘制蓝天,在上层绘制白云,再上层会执行小鸟。然后三层叠加以后就是一副小鸟在天空翱翔的图了。

二、效果与分析

好了,接下来看下今天的效果。

ok,可以看到一个简单的着色效果,其实原理很简单,首先呢,该图实际上是由7层组成:

例如下图。

那么如果我们需要给这幅图的某个位置着色,实际上是给某一层的非透明区域着色。实际上就转化为:

用户点击的(x,y)-> 判断落在哪一层的非透明区域 -> 然后给该层非透明区域着色。

ok,这样原理就叙述清楚了,实际上也是非常的简单,基于该原理,我们可以自定义一个View,然后一幅一幅去绘制图层,最后按照上述步骤去编写代码。不过,我们还有可以偷懒的地方,其实没必要我们自己去一个图层一个图层的绘制,我们可以利用Drawable去完成图层叠加的工作,我们有一类Drawable叫做LayerDrawable,对应的xml为layer-list,我们可以通过使用LayerDrawable极大的简化我们的工作。

三、编码与实现

上述已经描述很清楚了,我再给大家细化一下:

  1. layer-list中去定义我们的drawable
  2. 然后把该drawable作为我们View的背景
  3. 复写onTouchEvent方法
  4. 判断用户点击的坐标落在哪一层的非透明位置,改变该层非透明区域颜色
(一)layer-list
    <?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android">    <item        android:drawable="@drawable/eel_mask1"/>    <item        android:drawable="@drawable/eel_mask2"/>    <item        android:drawable="@drawable/eel_mask3"/>    <item        android:drawable="@drawable/eel_mask4"/>    <item        android:drawable="@drawable/eel_mask5"/>    <item        android:drawable="@drawable/eel_mask6"/>    <item        android:drawable="@drawable/eel_mask7"/></layer-list>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

ok,这样我们的drawable就ok了~~没撒说的,不过layer-list可以做很多事情,大家可以关注下。

(二)View代码
package com.zhy.colour_app_01;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Color;import android.graphics.PorterDuff;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.graphics.drawable.LayerDrawable;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import java.util.Random;/** * Created by zhy on 15/5/14. */public class ColourImageBaseLayerView extends View{    private LayerDrawable mDrawables;    public ColourImageBaseLayerView(Context context, AttributeSet attrs)    {        super(context, attrs);        mDrawables = (LayerDrawable) getBackground();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)    {        setMeasuredDimension(mDrawables.getIntrinsicWidth(), mDrawables.getIntrinsicHeight());    }    @Override    public boolean onTouchEvent(MotionEvent event)    {        final float x = event.getX();        final float y = event.getY();        if (event.getAction() == MotionEvent.ACTION_DOWN)        {            Drawable drawable = findDrawable(x, y);            if (drawable != null)                drawable.setColorFilter(randomColor(), PorterDuff.Mode.SRC_IN);        }        return super.onTouchEvent(event);    }    private int randomColor()    {        Random random = new Random();        int color = Color.argb(255, random.nextInt(256), random.nextInt(256), random.nextInt(256));        return color;    }    private Drawable findDrawable(float x, float y)    {        final int numberOfLayers = mDrawables.getNumberOfLayers();        Drawable drawable = null;        Bitmap bitmap = null;        for (int i = numberOfLayers - 1; i >= 0; i--)        {            drawable = mDrawables.getDrawable(i);            bitmap = ((BitmapDrawable) drawable).getBitmap();            try            {                int pixel = bitmap.getPixel((int) x, (int) y);                if (pixel == Color.TRANSPARENT)                {                    continue;                }            } catch (Exception e)            {                continue;            }            return drawable;        }        return null;    }}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86

ok,代码也比较简单,首先我们把drawable作为view的背景,然后在构造中获取drawable(LayerDrawable)。接下来复写onTouchEvent,捕获用户点击的(x,y),根据(x,y)去找出当前点击的是哪一层(必须点击在非透明区域),最后通过设置setColorFilter去改变颜色即可~很easy吧最后贴下布局文件:

(三)布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"                xmlns:tools="http://schemas.android.com/tools"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:paddingLeft="@dimen/activity_horizontal_margin"                android:paddingRight="@dimen/activity_horizontal_margin"                android:paddingTop="@dimen/activity_vertical_margin"                android:paddingBottom="@dimen/activity_vertical_margin"                tools:context=".MainActivity">    <com.zhy.colour_app_01.ColourImageBaseLayerView        android:background="@drawable/eel"        android:layout_width="match_parent"        android:layout_centerInParent="true"        android:layout_height="match_parent"/></RelativeLayout>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

ok~基于层的的填充就介绍完了,下一篇基于边界的填充,敬请期待~~

 

群号:264950424,欢迎入群

   

源码点击下载

   

微信公众号:hongyangAndroid
  (欢迎关注,第一时间推送博文信息)
 

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
实现不规则封闭区域填充颜色,可以使用Canvas的drawPath()方法和Paint的setShader()方法来实现。具体步骤如下: 1. 创建一个自定义View类 ```java public class MyView extends View { private Path mPath; private Paint mPaint; public MyView(Context context) { super(context); init(); } public MyView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { mPaint = new Paint(); mPaint.setStyle(Paint.Style.FILL); mPaint.setAntiAlias(true); mPath = new Path(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawPath(mPath, mPaint); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mPath.reset(); mPath.moveTo(event.getX(), event.getY()); return true; case MotionEvent.ACTION_MOVE: mPath.lineTo(event.getX(), event.getY()); break; default: return false; } invalidate(); return true; } } ``` 在上面的代码中,我们创建了一个自定义View类MyView,并在构造函数中初始化了Paint和Path对象。在init()方法中,我们设置Paint的样式为填充,并开启了抗锯齿。在onDraw()方法中,我们使用Canvas的drawPath()方法来绘制Path对象。在onTouchEvent()方法中,我们根据用户的触摸事件来更新Path对象,并调用invalidate()方法来刷新视图。 2. 在MainActivity中添加自定义View ```java public class MainActivity extends AppCompatActivity { private MyView mView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mView = findViewById(R.id.my_view); } public void setFillColor(View view) { int color = ContextCompat.getColor(this, R.color.fill_color); mView.getPaint().setShader(new LinearGradient(0, 0, getWidth(), getHeight(), color, color, Shader.TileMode.REPEAT)); mView.invalidate(); } } ``` 在上面的代码中,我们在MainActivity中添加了一个自定义View,并在setFillColor()方法中设置填充颜色。这里我们使用了ContextCompat.getColor()方法来获取颜色值,并使用LinearGradient来创建着色器。最后,我们调用invalidate()方法刷新视图,使填充颜色生效。 3. 在布局文件中添加自定义View ```xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.fillcolor.MainActivity"> <com.example.fillcolor.MyView android:id="@+id/my_view" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ffffff" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="16dp" android:onClick="setFillColor" android:text="Set Fill Color" /> </RelativeLayout> ``` 在上面的布局文件中,我们添加了一个RelativeLayout,并在其中添加了一个自定义View和一个Button。自定义View的背景颜色设置为白色,以便更好地显示填充颜色。当用户点击Button时,将调用setFillColor()方法来设置填充颜色。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值