http://blog.chinaunix.net/uid-20680966-id-4961553.html
ndk编译时出错:
undefined reference to `__android_log_print'
原因是默认情况下,存在src/main/jni文件夹时,gradle生成脚本会执行ndk编译生成操作,但是,编译生成方式并不是像以前那样用ndk-build去处理Android.mk Application.mk等
解决方法:
通过在app的build.gradle中
android {
加入配置:
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir 'src/main/libs'
}
一个可以编译通过的app的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
v7包actionbar设置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(); } }
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; } }