5.31 Android studio NDK配置、v 7パッケージのactionbar設定overflowはいつも表示されます。android 5の水の波紋view


http://blog.chinaunix.net/uid-20680966-id-4961553.html
ndkコンパイル中にエラーが発生しました。
undefined reference to_u uandroid_ロゴprint
デフォルトの場合、src/main/jniフォルダが存在する場合、gradle生成スクリプトはndkコンパイル生成操作を行いますが、コンパイル生成方式は以前のようにAndroid.mk Apple.mkなどをndk-buildで処理するものではありません。
解決方法:appのbuild.gradleの中でandroid{加入構成:sourceSets.main}    jni.srrDirs=[]    jniLibs.srDir'src/main/libs's
コンパイルできるアプリのbuild.gradle
android {
    compileSdkVersion 21
    buildToolsVersion '21.1.1'

    defaultConfig {
        applicationId "com.michele.funnypic"
        minSdkVersion 9
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"

        ndk{
            moduleName "PUtil"  //   (so)    
        }
    }
    sourceSets.main {
        jni.srcDirs = []
        jniLibs.srcDir 'src/main/libs'
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
Android画像処理神器BitmapFunソース分析:
http://www.2cto.com/kf/201408/322931.html
v 7パッケージactionback設定overflowは常に表示されます。
http://blog.csdn.net/jwzhangjie/article/details/28852967
private void setOverflowShowingAlways() {  
    try {  
        ViewConfiguration config = ViewConfiguration.get(this);  
        Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");  
        menuKeyField.setAccessible(true);  
        menuKeyField.setBoolean(config, false);  
    } catch (Exception e) {  
        e.printStackTrace();  
    }  
}  
android 5の水の波紋view
http://blog.csdn.net/jason0539/article/details/42755871
public class JasonBreathTextView extends TextView {

	private JasonBreathCircle breathCircle;

	public JasonBreathTextView(Context context) {
		super(context);
	}

	public JasonBreathTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
		breathCircle = new JasonBreathCircle(context);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		// TODO Auto-generated method stub
		super.onSizeChanged(w, h, oldw, oldh);
		breathCircle.initParameters(this);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		breathCircle.setCircleCenter((int) event.getX(), (int) event.getY());
		return super.onTouchEvent(event);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		breathCircle.draw(canvas);
		super.onDraw(canvas);
	}

	/**
	 *       
	 */
	public void startReveal() {
		breathCircle.start();
	}

	/**
	 *       
	 */
	public void stopReveal() {
		breathCircle.stop();
	}

}



public class JasonBreathCircle {
	private static int DIFFUSE_GAP = 2; //       
	private static final int INVALIDATE_DURATION = 10; //          

	private Context mContext;
	private boolean needToDrawReveal = false;//      
	//          
	private boolean isLargerMode = true;//     
	private Paint mPaintReveal;//   
	private int mCircleCenterX;//   x
	private int mCircleCenterY;//   y
	private int mCurRadius;//     
	private int mMaxRadius;//     
	//           ,                
	private View mParentView;//      
	private int mParentHeight;//     
	private int mParentWidth;//     

	// ================     (    )===============

	/**
	 *       ,     initParameters        ,      draw 
	 * 
	 * @param context
	 */
	public JasonBreathCircle(Context context) {
		mContext = context;
		initPaint();
	}

	/**
	 *   view,       ,  ,            
	 * 
	 * @param view
	 */
	public void initParameters(View view) {
		this.mParentView = view;
		//            
		mParentHeight = mParentView.getHeight();
		mParentWidth = mParentView.getWidth();
		//        
		mMaxRadius = (int) Math.hypot(view.getHeight(), view.getWidth()) / 2;
		//              
		mCircleCenterX = mParentWidth / 2;
		mCircleCenterY = mParentHeight / 2;
	}

	/**
	 *     
	 * 
	 * @param canvas
	 */
	public void draw(Canvas canvas) {
		if (needToDrawReveal) {
			canvas.save();
			canvas.drawCircle(mCircleCenterX, mCircleCenterY, mCurRadius,
					mPaintReveal);
			canvas.restore();
			if (isLargerMode && mCurRadius < mMaxRadius) {
				mCurRadius += DIFFUSE_GAP;//     
				postRevealInvalidate();
			} else if (mCurRadius > 0 && !isLargerMode) {
				//           
				mCurRadius -= DIFFUSE_GAP;//     
				postRevealInvalidate();
			} else {//     
				isLargerMode = !isLargerMode;
				//           , 0       x, 0    y
				setCircleCenter(JasonRandomUtil.nextInt(0, mParentWidth),
						JasonRandomUtil.nextInt(0, mParentHeight));
				//      ,   ,         ,            
				if (!isLargerMode) {
					mCurRadius = mMaxRadius;
				}
				postRevealInvalidate();
			}
		}
	}

	// ===============    ===============
	/**
	 *     
	 */
	public void start() {
		if (needToDrawReveal) {
			return;
		}
		needToDrawReveal = true;
		postRevealInvalidate();
	}

	/**
	 *     
	 */
	public void stop() {
		if (!needToDrawReveal) {
			return;
		}
		needToDrawReveal = false;
		reset();
		postRevealInvalidate();
	}

	/**
	 *     
	 * 
	 * @param x
	 * @param y
	 */
	public void setCircleCenter(int x, int y) {
		mCircleCenterX = x;
		mCircleCenterY = y;
		mMaxRadius = JasonRadiusUtil.getMaxRadius(mCircleCenterX,
				mCircleCenterY, mParentWidth, mParentHeight);
	}

	/**
	 *            ,    
	 * 
	 * @param isHollow
	 */
	public void setHollow(boolean isHollow) {
		mPaintReveal.setStyle(isHollow ? Paint.Style.STROKE : Paint.Style.FILL);
	}

	// ================    ===============
	/**
	 *   
	 */
	private void reset() {
		mCurRadius = 0;
		isLargerMode = true;
	}

	/**
	 *      
	 */
	private void initPaint() {
		mPaintReveal = new Paint();
		mPaintReveal.setColor(mContext.getResources().getColor(
				R.color.jason_bg_common_green_light));
		mPaintReveal.setAntiAlias(true);
	}

	/**
	 *   
	 */
	private void postRevealInvalidate() {
		mParentView.postInvalidateDelayed(INVALIDATE_DURATION);
	}
}

自分で書いた水の波紋効果(他の人のdemoに基づいて修正したもの)は、drawableに基づくもの:
package com.michele.funnypic.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.text.Editable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.TextView;

import com.michele.funnypic.drawable.RippleDrawable;
import com.michele.funnypic.plug.PlugLoader;
import com.michele.funnypic.util.EmojParperUtil;

/**
 *
 * Created by touch_ping on 15/5/29.
 */
public class AppTextView extends TextView {
    private RippleDrawable drawable;
    public AppTextView(Context context) {
        super(context);
        init();
    }

    public AppTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public AppTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public AppTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init () {
        drawable = new RippleDrawable(0x00000000, 0x33000000);
        setBackgroundDrawable(drawable);

        PlugLoader.getPlug().init(this);
    }

    public Editable getEmoijUtfText () {
        return EmojParperUtil.parperWeiChatTexts(super.getText());
    }

    public void clearStat() {
        drawable.clearStat();
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        CharSequence ch = EmojParperUtil.parperWeiChatEmojis(text);
        super.setText(ch, type);
    }

//    @Override
//    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//        super.onSizeChanged(w, h, oldw, oldh);
//        drawable.init(w, h);
//    }

    @Override
    public boolean onTouchEvent(final MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                drawable.drawDown((int)event.getX(), (int)event.getY());
                return super.onTouchEvent(event);
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                drawable.drawUp();
                AppTextView.this.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        AppTextView.super.onTouchEvent(event);
                    }
                },100);
                return true;
        }
        return super.onTouchEvent(event);
    }
}






package com.michele.funnypic.drawable;

import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.view.ViewConfiguration;

public class RippleDrawable extends Drawable {
	
	
	 private static final int INVALIDATE_DURATION = 20; //           
	    private static int DIFFUSE_GAP = 10;                  //        
	    private static int TAP_TIMEOUT;                   //            
	      
	    private int viewWidth;                            //       
	    private int viewHeight;
	    private int pointX;                               //      (   )  
	    private int pointY;  
	    private int maxRadio;                             //         
	    private int shaderRadio;  
	      
	    private Paint bottomPaint;                        //    
	    private Paint colorPaint;  
	      
	    private boolean isPushButton;                     //           
	    
	    
	    private int eventX;  
	    private int eventY;  
	    private long downTime = 0;  
	    
	    Handler handler = new Handler(Looper.getMainLooper()) {
			@Override
			public void handleMessage(Message msg) {
				invalidateSelf();
			}
	    };
	    
	    
	public RippleDrawable(int backgroundColor,int waveColor) {
		colorPaint = new Paint();  
        bottomPaint = new Paint();  
        colorPaint.setColor(waveColor);  
        bottomPaint.setColor(backgroundColor);   
        
        TAP_TIMEOUT = ViewConfiguration.getLongPressTimeout();  
	}
//
//	public void init (int viewWitdh,int viewHeight) {
//		this.viewWidth = viewWitdh;
//		this.viewHeight = viewHeight;
//	}
	
	/** 
     *           
     */  
    private void countMaxRadio() {
        Rect bounds = getBounds();

         viewWidth = bounds.left + bounds.width();
         viewHeight = bounds.bottom + bounds.height();
        if(viewWidth > viewHeight){  
            if(eventX < viewWidth / 2){  
                maxRadio = viewWidth - eventX;  
            }else{  
                maxRadio = viewWidth / 2 + eventX;  
            }  
        }else{  
            if(eventY < viewHeight / 2){  
                maxRadio = viewHeight - eventY;  
            }else{  
                maxRadio = viewHeight / 2 + eventY;  
            }  
        }  
    }  
    
	

	@Override
	public void draw(Canvas canvas)
	{
		canvas.drawRect(getBounds(), bottomPaint);
		if(!isPushButton) return; //              
//		        //          
		        canvas.drawRect(pointX, pointY, pointX + viewWidth, pointY + viewHeight, bottomPaint);
		        canvas.save();
		        //          
		        canvas.clipRect(pointX, pointY, pointX + viewWidth, pointY + viewHeight);  
		        canvas.drawCircle(eventX, eventY, shaderRadio, colorPaint);  
		        canvas.restore();  
		        //            
		        if(shaderRadio < maxRadio){  
//		            postInvalidateDelayed(INVALIDATE_DURATION,   
//		                    pointX, pointY, pointX + viewWidth, pointY + viewHeight); 
		            handler.sendEmptyMessageDelayed(0, INVALIDATE_DURATION);
//		            postInvalidateDelayed(delayMilliseconds, left, top, right, bottom)
		            shaderRadio += DIFFUSE_GAP;  
		        }else{
                    clearStat();
		        }  
	}

    
    /** 
     *     (     )
     */  
    public void clearStat(){
        downTime = 0;  
        DIFFUSE_GAP = 10;  
        isPushButton = false;  
        shaderRadio = 0;
        invalidateSelf();
    }
      
	
	
	public void drawDown(int x,int y) {
		//          
        if(downTime == 0){  
            downTime = SystemClock.elapsedRealtime();  
        }  
        eventX = x;  
        eventY = y;  
        //        
        countMaxRadio();  
        isPushButton = true;  
        invalidateSelf();
	}
	
	public void drawUp () {
		if(SystemClock.elapsedRealtime() - downTime < TAP_TIMEOUT){  
            DIFFUSE_GAP = 30;  
            invalidateSelf();  
        }else{
            clearStat();
        }  
	}

	@Override
	public void setAlpha(int alpha)
	{
		bottomPaint.setAlpha(alpha);
	}

	@Override
	public void setColorFilter(ColorFilter cf)
	{
		bottomPaint.setColorFilter(cf);
	}

	@Override
	public int getOpacity()
	{
		return PixelFormat.TRANSLUCENT;
	}

}