2017年5月24日星期三

paint之setXfermode.根据图片轨迹把图片画上去

本篇重点是: 根据设置的图片轨迹之上画上去资源图片.
比如下面: 可以看到他的框架是六角形.那么放上去图片时会根据那个轨迹贴上去.


研究一下网址.对理解有帮助
http://blog.csdn.net/harvic880925/article/details/51264653

核心代码是:
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));

使用方法:
其中setImageFrame是 setImageMask是轨迹用的框.
setImageFrame是 边框, setImageResource是要根据轨迹画上去的 资源图片

mIvTeamImage.setImageMask(R.drawable.join_a_team_teamlogo_frame);//// TODO: 2017. 5. 24. 이미지를 올려놓아야 한다mIvTeamImage.setImageFrame(R.drawable.bg_team_image_324_362);
mIvTeamImage.setImageResource(R.drawable.teamlogo_no_img);

贴出全部代码.

public class MaskImage extends ImageView {    Bitmap mMask        = null;    Bitmap mFrame       = null;    int mFrameResId     = -1;
    Bitmap mOriBmp      = null;    //Bitmap mResult;    private int m_nWidth            = -1;    private int m_nHeight           = -1;    private int m_nResId            = -1;    private String m_szPath         = null;    private boolean m_bNeedRemask   = false;
    private Canvas mCanvas = null;
    public MaskImage(Context context) {        super(context);
    }
    public MaskImage(Context context, AttributeSet attrs) {        super(context, attrs);    }
    public MaskImage(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }
    public void setImageMask(int resource) {        if(mMask != null) {            mMask.recycle();        }        mMask = BitmapFactory.decodeResource(getResources(), resource);    }

    public void setImageFrame(int resource) {        if(mFrameResId == resource)            return;
        if(mFrame != null) {            mFrame.recycle();        }        if (resource == 0) {            mFrame = null;            mFrameResId = -1;            return;        }        mFrameResId = resource;        mFrame = BitmapFactory.decodeResource(getResources(), resource);        m_bNeedRemask = true;    }

    @Override    public void setImageResource(final int resId) {        if(m_nResId == resId) {            return;        }        m_bNeedRemask = true;        m_nResId = resId;        m_szPath = null;        mOriBmp = null;        invalidate();    }
    @Override    public void setImageBitmap(Bitmap bm) {        mOriBmp = bm;        m_nResId = -1;        m_szPath = null;        m_bNeedRemask = true;        invalidate();    }
    public void setImagePath(String imagePath) {        if(m_szPath != null && m_szPath.equals(imagePath)) {            return;        }
        mOriBmp = null;        m_nResId = -1;        m_szPath = imagePath;        m_bNeedRemask = true;        invalidate();    }

    private void  createMaskBitmap(Bitmap original)    {        if(mMask != null) {            if(mMask.getWidth() != m_nWidth || mMask.getHeight() != m_nHeight) {                Bitmap bmp = Bitmap.createScaledBitmap(mMask, m_nWidth, m_nHeight, true);                mMask.recycle();                mMask = bmp;            }        }
        if(mFrame != null) {            if(mFrame.getWidth() != m_nWidth || mFrame.getHeight() != m_nHeight) {                Bitmap bmp = Bitmap.createScaledBitmap(mFrame, m_nWidth, m_nHeight, true);                mFrame.recycle();                mFrame = bmp;            }        }
        if(original != null) {            if(original.getWidth() != m_nWidth || original.getHeight() != m_nHeight) {                Bitmap bmp = Bitmap.createScaledBitmap(original, m_nWidth, m_nHeight, true);                original.recycle();                original = bmp;            }        }
        Bitmap bitmap = Bitmap.createBitmap(m_nWidth, m_nHeight, Config.ARGB_8888);        Canvas mCanvas = new Canvas(bitmap);        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));        if(original != null) {            mCanvas.drawBitmap(original, 0, 0, null);        }        mCanvas.drawBitmap(mMask, 0, 0, paint);        paint.setXfermode(null);        if (null != mFrame) {            mCanvas.drawBitmap(mFrame, 0, 0, paint);        }        super.setImageBitmap(bitmap);    }
    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        if(changed && m_nWidth == -1) {            m_nWidth = right - left;            m_nHeight = bottom - top;        }    }
    @Override    protected void onDraw(Canvas canvas) {        if(m_bNeedRemask) {            Bitmap bmp = null;            if(m_nResId != -1) {                bmp = BitmapFactory.decodeResource(getResources(), m_nResId);            } else if(m_szPath != null) {                bmp = BitmapFactory.decodeFile(m_szPath);            } else if(mOriBmp != null)           {                bmp = mOriBmp;            }            createMaskBitmap(bmp);            m_bNeedRemask = false;        }        super.onDraw(canvas);    }}

2016年12月1日星期四

页面取消光标

解决方法:
在EditText的父级控件中找一个,设置成 
android:focusable="true" 
android:focusableInTouchMode="true" 

2016年11月14日星期一

关于 service的理解

  网上有很多大神对service已经有了 详细的介绍. 在这里 我只是记录下 我关于service的调试跟理解.


1. service 分为两种开启方法 startService与 bindService.
 
>startSetvice开启的话 即使应用关闭 它也会正常使用.
  并且退出应用->重进应用再开启startService时 如果已经存在该服务, 是不会重启服务的.
  最开始开启服务时的顺序是 onCreate > onStartCommand 
  如果服务已经开启再开启服务时 onStartCommand

2.bindService开启的话 随着应用的关闭而会被关闭. 即使你没有使用 unbinderService.
 
>所以使用contentService来链接时候只能是单向链接.
>要注意的是 aidlService的 通信见链接Service也是 单次链接.因为他是通过Ibinder链接的(bindService)

3.IntentService是 异步请求.他的服务器启动并不在 main thread 进行.并且他会自动 stopSelf 来停止服务. 所以他也是单次调用. 因为你不能长期挂起.


 

2016年11月3日星期四

注解的使用(Annotation)

  此帖用来写 本人对注解使用的理解. 并且考虑了下 什么状态下能使用注解.

考虑场景 1: 在你使用注解的地方. 程序调用此地方的方法(或者接口)时 让系统自动调用此方法.
          比如:

ClassA里调用了 注解Anotation时
public class ClassA {
@Anotation(value="kirsong")
public void showA(String name){
System.out.println(name);
}
}

当调用类ClassA的时候 根据方法映射调用 showA方法.

Method methodAnotation=ClassA.class.getDeclaredMethod("showA", new Class[]{String.class});
Anotation an=null;
if(methodAnotation.isAnnotationPrese
//判断该方法是否存在注解
if((an=methodAnotation.getAnnotation(Anotation.class))!=null){
try {
methodAnotation.invoke(mj, an.value());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}


考虑场景2: 根据传送的数据, 分析数据中的注解类并调用他

首先声明注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Anotation {
String value() default "val1";
}

创建使用到注解的类
public class ClassA {
@Anotation(value="kirsong")
public void showA(String name){
System.out.println(name);
}
@Anotation
public void showB(String name){
System.out.println(name);
}
public void showC(String name){
System.out.println(name);
}
}

创建根据注解分析器,并调用
public class TargetAnnotation {

public void setPust(Object cls){
try {
Method[] md=cls.getClass().getDeclaredMethods();
Anotation an=null;
for(Method method:md){
if((an=method.getAnnotation(Anotation.class))!=null){
method.invoke(cls, an.value());
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}

使用方法
System.out.print("场景3\n");
ClassA ca=new ClassA();
TargetAnnotation target=new TargetAnnotation();
target.setPust(ca);


使用场景3. 使用注解调用接口

定义接口

public interface InterFaceA {
@Anotation(value="intera")
void interA(String value);
}

调用接口中的注解方法

public void setInterfacePust(Object cls){
try {

Class<?>[] interfaces = cls.getClass().getInterfaces(); 
for(Class<?> interClas:interfaces){
Method[] md=interClas.getDeclaredMethods();
Anotation an=null;
cls.getClass().getInterfaces();
for(Method method:md){
if((an=method.getAnnotation(Anotation.class))!=null){
method.invoke(cls, an.value());
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}

调用
InterFaceA intera=new InterFaceA(){

@Override
public void interA(String value) {
System.out.print(value);
}
};
target.setInterfacePust(intera);




2016年10月11日星期二

requestDisallowInterceptTouchEvent的使用

 requestDisallowInterceptTouchEvent(true)方法是用来子View告诉父容器不要拦截我们的事件的,但是这个代码放的位置很重要,可能导致失效。首先我们要知道父类肯定能收到Down事件的,因为这个是事件的起源,系统默认在VIewGroup里把requestDisallowInterceptTouchEvent里把子View对于Down事件的拦截权利剥削了,有了这个Down,它才会决定后面的事件是否传给子类,看代码
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. public boolean onInterceptTouchEvent(MotionEvent ev) {  
  3.     switch (ev.getAction()) {  
  4.     case MotionEvent.ACTION_DOWN:  
  5.         return false;  
  6.     case MotionEvent.ACTION_MOVE:   //表示父类需要  
  7.         if(true) {  
  8.             return true;  
  9.         }  
  10.         else {  
  11.             return false;  
  12.         }  
  13.     case MotionEvent.ACTION_UP:  
  14.         return true;  
  15.     default:  
  16.         break;  
  17.     }  
  18.     // TODO Auto-generated method stub  
  19.     Log.e("TestView","父容器拦截");  
  20.     return false;    //如果设置拦截,除了down,其他都是父类处理  
  21. }  
代码可以看出,父类拦截了move和up事件,我们怎么让他失效呢,答案是在接受到down事件的方法里,而不是一开始就设置这个true标志,为什么呢,因为Viewgroup会在收到down事件时重置这个标志,如果太早设置就无效了。所以
子类应该这么写
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. public boolean dispatchTouchEvent(MotionEvent event) {      
  3.     // TODO Auto-generated method stub  
  4.     getParent().requestDisallowInterceptTouchEvent(true);         
  5.     return super.dispatchTouchEvent(event);  
  6. }  
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. 子类在收到父类的down事件时,去拦截,当然如果父类拦截了down事件,子类就没办法拦截他的其他事件了,  

我这里都拦截了,当然down的时候必须拦截,其他让不让父View收到up事件就看情况,move父view肯定也收不到。