-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent.json
1 lines (1 loc) · 64 KB
/
content.json
1
{"meta":{"title":"丿歌吟有梦","subtitle":"不要让任何事成为你不学习的理由!","description":"Android博客网站","author":"丁军伟","url":"http://itdais.com"},"pages":[{"title":"tags","date":"2016-07-05T15:29:13.000Z","updated":"2016-07-05T15:31:45.162Z","comments":false,"path":"tags/index.html","permalink":"http://itdais.com/tags/index.html","excerpt":"","text":""}],"posts":[{"title":"BottomSheet使用详解","slug":"BottomSheet使用详解","date":"2016-10-11T16:00:00.000Z","updated":"2016-10-13T02:05:46.051Z","comments":true,"path":"2016/10/12/BottomSheet使用详解/","link":"","permalink":"http://itdais.com/2016/10/12/BottomSheet使用详解/","excerpt":"","text":"BottomSheet使用详解Android Support Library 23.2里的 Design Support Library新加了一个Bottom Sheets控件,Bottom Sheets顾名思义就是底部操作控件,用于在屏幕底部创建一个可滑动关闭的视图,可以替代对话框和菜单。其中包含BottomSheets、BottomSheetDialog和BottomSheetDialogFragment三种可以使用。 BottomSheets常见的效果如图,并且在国内的知乎、百度地图上也是可以看到效果。 首先我们学习使用BottomSheets,BottomSheets其实也是依赖于Behavior机制的使用。先引用依赖,最新的design包已经到24了1compile 'com.android.support:design:24.2.1' BottomSheets在布局文件xml中的使用,BottomSheets需要配合CoordinatorLayout控件12345678910111213141516171819202122232425<?xml version=\"1.0\" encoding=\"utf-8\"?><android.support.design.widget.CoordinatorLayout android:id=\"@+id/cl\" xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:app=\"http://schemas.android.com/apk/res-auto\" android:layout_width=\"match_parent\" android:layout_height=\"match_parent\" android:fitsSystemWindows=\"true\"> <android.support.v4.widget.NestedScrollView android:id=\"@+id/bottom_sheet\" android:layout_width=\"match_parent\" android:layout_height=\"wrap_content\" app:behavior_hideable=\"true\" app:behavior_peekHeight=\"50dp\" app:layout_behavior=\"@string/bottom_sheet_behavior\"> <LinearLayout android:layout_width=\"match_parent\" android:layout_height=\"wrap_content\" android:orientation=\"vertical\"> <!-- 你自己的代码--> </LinearLayout> </android.support.v4.widget.NestedScrollView></android.support.design.widget.CoordinatorLayout> 其中包含三个属性123app:behavior_hideable="true"app:behavior_peekHeight="0dp"app:layout_behavior="@string/bottom_sheet_behavior" app:behavior_peekHeight=”50dp” peekHeight是当Bottom Sheets关闭的时候,底部我们能看到的高度,默认是0不可见。 app:behavior_hideable=”true” hideable是当我们拖拽下拉的时候,bottom sheet是否能全部隐藏。 layout_behavior指向bottom_sheet_behavior,代表这是一个bottom Sheets 在java代码中的使用12345678910111213141516171819202122BottomSheetBehavior behavior; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bottom_sheet); View bottomSheet = findViewById(R.id.bottom_sheet); behavior = BottomSheetBehavior.from(bottomSheet); behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { @Override public void onStateChanged(@NonNull View bottomSheet, int newState) { //这里是bottomSheet状态的改变 } @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) { //这里是拖拽中的回调,根据slideOffset可以做一些动画 } }); } behavior_hideable对应代码 behavior.setHideable(false);behavior_peekHeight对应代码 behavior.setPeekHeight(50); setBottomSheetCallback可以监听回调的状态,onStateChanged监听状态的改变,onSlide是拖拽的回调,onStateChanged可以监听到的回调一共有5种: STATE_HIDDEN: 隐藏状态。默认是false,可通过app:behavior_hideable属性设置。 STATE_COLLAPSED: 折叠关闭状态。可通过app:behavior_peekHeight来设置显示的高度,peekHeight默认是0。 STATE_DRAGGING: 被拖拽状态 STATE_SETTLING: 拖拽松开之后到达终点位置(collapsed or expanded)前的状态。 STATE_EXPANDED: 完全展开的状态。BottomSheets控件配合NestedScrollView、RecyclerView使用效果会更好,合理的使用让APP逼格满满。 我们需要在按钮按钮上添加对BottomSheets的显示和隐藏 12345if(behavior.getState() == BottomSheetBehavior.STATE_EXPANDED) { behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);}else { behavior.setState(BottomSheetBehavior.STATE_EXPANDED);} 效果如图: design24.2.1的BottomSheets和23.2.0的BottomSheet有很大的区别,design23.2.0的包中如果你使用了BottomSheet,可以在屏幕外任何位置上拉即可拉出来布局,在24.2.1中没有了这个效果。 BottomSheetDialogBottomSheetDialog应该是最实用的控件,也是使用率非常高的控件。它可以替代大多数网格显示和列表展示的dialog和popupwindow,默认宽度撑满,并且在BottomSheetDialog 区域中向下滑动也让对话框消失。 首先写一个dialog展示的xml,dialog中xml可以不用被CoordinatorLayout包裹,但是还是推荐实用推荐的滑动控件NestedScrollView1234567891011121314151617181920212223242526272829<?xml version=\"1.0\" encoding=\"utf-8\"?><android.support.v4.widget.NestedScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\" android:layout_width=\"match_parent\" android:layout_height=\"match_parent\"> <LinearLayout android:layout_width=\"match_parent\" android:layout_height=\"match_parent\" android:orientation=\"vertical\"> <TextView android:onClick=\"doclick\" android:layout_width=\"match_parent\" android:layout_height=\"100dp\" android:background=\"@color/colorPrimary\" android:gravity=\"center\" android:text=\"啦啦啦啦啦啦啦啦啦\" android:textColor=\"@color/white\" android:textSize=\"18sp\"/> <ImageView android:onClick=\"doclick\" android:layout_width=\"match_parent\" android:layout_height=\"wrap_content\" android:scaleType=\"centerCrop\" android:src=\"@drawable/banner\"/> </LinearLayout></android.support.v4.widget.NestedScrollView> 编写java代码1234BottomSheetDialog dialog = new BottomSheetDialog(this);View view = getLayoutInflater().inflate(R.layout.dialog_bottom_sheet, null);dialog.setContentView(view);dialog.show(); 只需要四行我们就可以展示BottomSheets效果的dialog,高度为你设置的behavior_peekHeight或者默认高度,宽度撑满。在很多情况底部显示dialog的时候,都可以考虑实用BottomSheetDialog来实现。效果如图: BottomSheetDialogFragmentBottomSheetDialogFragment可以帮助我们实现全屏的BottomSheet展示效果。新建一个类继承BottomSheetDialogFragment xml使用BottomSheetDialog的布局样式,我们直接看java代码 1234567891011121314151617181920212223242526public class FullSheetDialogFragment extends BottomSheetDialogFragment { private BottomSheetBehavior mBehavior; @Override public Dialog onCreateDialog(Bundle savedInstanceState) { BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState); View view = View.inflate(getContext(), R.layout.dialog_bottom_sheet, null); dialog.setContentView(view); mBehavior = BottomSheetBehavior.from((View) view.getParent()); return dialog; } @Override public void onStart() { super.onStart(); //默认全屏展开 mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); } public void doclick(View v) { //点击任意布局关闭 mBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); }} 调用BottomSheetDialogFragment展示 1new FullSheetDialogFragment().show(getSupportFragmentManager(), \"dialog\"); BottomSheetDialogFragment的效果跟BottomSheetDialog差不多,根据情况选择。效果如图: BottomSheetDialog就介绍到此,如果有错误请指出,谢谢。 参考:泡在网上的日子BottomSheets的使用 个人网站 歌吟有梦 itdais.com 更多内容可以关注我的公众号:丁军伟Dev(或者搜索DingAndroid)","categories":[],"tags":[{"name":"Android","slug":"Android","permalink":"http://itdais.com/tags/Android/"},{"name":"Gradle","slug":"Gradle","permalink":"http://itdais.com/tags/Gradle/"}]},{"title":"Android Studio运行时候报packageOfficialDebug错误","slug":"Android Studio运行时候报packageOfficialDebug错误","date":"2016-10-10T16:00:00.000Z","updated":"2016-10-13T02:00:31.032Z","comments":true,"path":"2016/10/11/Android Studio运行时候报packageOfficialDebug错误/","link":"","permalink":"http://itdais.com/2016/10/11/Android Studio运行时候报packageOfficialDebug错误/","excerpt":"","text":"Android Studio运行时候报packageOfficialDebug错误报错信息为 Error:A problem was found with the configuration of task’:watch:packageOfficialDebug’.File ‘…\\build\\intermediates\\res\\resources-official-debug-stripped.ap_’ specified for property ‘resourceFile’ does not exist. 解决方法一:这个大多数原因是开启了混淆造成的,关闭Debug模式下的混淆开关后重新编译即可,代码如下: 1234567891011121314buildTypes { release { buildConfigField("boolean", "LOG_DEBUG", "false") minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { minifyEnabled false shrinkResources false buildConfigField("boolean", "LOG_DEBUG", "true") proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } minifyEnabled即以前的runProguard,用来控制是否混淆。 shrinkResources为true时自动去掉多余资源。 注:Gradle2.0以上的版本minifyEnabled字段为true时已经包含了shrinkResources,在代码优化时会自动去掉多余资源,所以在打正式包时也不需要设置shrinkResources字段。 解决方法二:Android Studio2.0以上有了Instant Run功能,很多情况下运行报错都跟Instant Run有关进入File –> Setting(Ctrl+Alt+S)找到InstantRun功能,把InstantRun功能关闭","categories":[],"tags":[{"name":"Android","slug":"Android","permalink":"http://itdais.com/tags/Android/"},{"name":"Gradle","slug":"Gradle","permalink":"http://itdais.com/tags/Gradle/"}]},{"title":"AS运行时异常(一)","slug":"AS运行时异常(一)","date":"2016-09-25T13:01:00.000Z","updated":"2016-09-05T13:35:22.539Z","comments":true,"path":"2016/09/25/AS运行时异常(一)/","link":"","permalink":"http://itdais.com/2016/09/25/AS运行时异常(一)/","excerpt":"","text":"从Github上下载了一个demo ,但是Android Studio一直运行不成功,爆出了下面的错误1234Error:(1, 1) A problem occurred evaluating project ':app'.> Failed to apply plugin [id 'com.android.application'] > Gradle version 2.10 is required. Current version is 2.8. If using the gradle wrapper, try editing the distributionUrl in E:\\workspace\\GitHub\\RxJavaApp-master\\gradle\\wrapper\\gradle-wrapper.properties to gradle-2.10-all.zip Message提醒为: Warning:Gradle version 2.10 is required. Current version is 2.8. Ifusing the gradle wrapper 解决方法为:File - Project Structure(Ctrl+Alt+Shift+S) - Project - 更改Gradle Version 为2.10 附:因为我本地已经有了2.10的Gradle版本,所以如果你没有该版本请下载或者更高其他版本试试","categories":[],"tags":[{"name":"Android","slug":"Android","permalink":"http://itdais.com/tags/Android/"},{"name":"Gradle","slug":"Gradle","permalink":"http://itdais.com/tags/Gradle/"}]},{"title":"Android Session失效重连","slug":"Android-Session失效重连","date":"2016-09-08T02:26:57.000Z","updated":"2016-09-08T02:26:57.903Z","comments":true,"path":"2016/09/08/Android-Session失效重连/","link":"","permalink":"http://itdais.com/2016/09/08/Android-Session失效重连/","excerpt":"","text":"","categories":[],"tags":[]},{"title":"Glide Transform","slug":"Glide Transform圆型图片和圆角图片","date":"2016-08-28T13:10:49.000Z","updated":"2016-08-29T13:27:32.787Z","comments":true,"path":"2016/08/28/Glide Transform圆型图片和圆角图片/","link":"","permalink":"http://itdais.com/2016/08/28/Glide Transform圆型图片和圆角图片/","excerpt":"本文介绍Glide通过Transform转换圆形图片和圆角图片","text":"本文介绍Glide通过Transform转换圆形图片和圆角图片 1、圆形转换器123456789101112131415161718192021222324252627282930313233343536373839public class GlideCircleTransform extends BitmapTransformation { public GlideCircleTransform(Context context) { super(context); } @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { return circleCrop(pool, toTransform); } private static Bitmap circleCrop(BitmapPool pool, Bitmap source) { if (source == null) return null; int size = Math.min(source.getWidth(), source.getHeight()); int x = (source.getWidth() - size) / 2; int y = (source.getHeight() - size) / 2; // TODO this could be acquired from the pool too Bitmap squared = Bitmap.createBitmap(source, x, y, size, size); Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888); if (result == null) { result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); } Canvas canvas = new Canvas(result); Paint paint = new Paint(); paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); paint.setAntiAlias(true); float r = size / 2f; canvas.drawCircle(r, r, r, paint); return result; } @Override public String getId() { return getClass().getName(); }} 使用 Glide.with(context).load(url) .placeholder(R.drawable.def_header) .transform(new GlideCircleTransform(context)) .into(view); 2、圆角转换器可以传参设置圆角的角度,不传默认4 12345678910111213141516171819202122232425262728293031323334353637public class GlideRoundTransform extends BitmapTransformation { private static float radius = 0f; public GlideRoundTransform(Context context) { this(context, 4); } public GlideRoundTransform(Context context, int dp) { super(context); this.radius = Resources.getSystem().getDisplayMetrics().density * dp; } @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { return roundCrop(pool, toTransform); } private static Bitmap roundCrop(BitmapPool pool, Bitmap source) { if (source == null) return null; Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); if (result == null) { result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); } Canvas canvas = new Canvas(result); Paint paint = new Paint(); paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); paint.setAntiAlias(true); RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight()); canvas.drawRoundRect(rectF, radius, radius, paint); return result; } @Override public String getId() { return getClass().getName() + Math.round(radius); }} 使用 Glide.with(context).load(url) .placeholder(R.drawable.transparent) .transform(new GlideRoundTransform(context)) .into(view);","categories":[],"tags":[{"name":"Android","slug":"Android","permalink":"http://itdais.com/tags/Android/"},{"name":"图片加载","slug":"图片加载","permalink":"http://itdais.com/tags/图片加载/"},{"name":"Glide","slug":"Glide","permalink":"http://itdais.com/tags/Glide/"}]},{"title":"自定义圆型控件","slug":"自定义圆型控件","date":"2016-08-28T13:10:13.000Z","updated":"2016-08-29T13:23:28.640Z","comments":true,"path":"2016/08/28/自定义圆型控件/","link":"","permalink":"http://itdais.com/2016/08/28/自定义圆型控件/","excerpt":"自定义圆形控件,CircleImageView和RoundImageView,其中使用CircleImageView,可以被Glide使用使用RoundImageView,不可以被Glide使用,可以设置双边框","text":"自定义圆形控件,CircleImageView和RoundImageView,其中使用CircleImageView,可以被Glide使用使用RoundImageView,不可以被Glide使用,可以设置双边框 1、CircleImageView123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269public class CircleImageView extends ImageView { private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; private static final int COLORDRAWABLE_DIMENSION = 2; private static final int DEFAULT_BORDER_WIDTH = 0; private static final int DEFAULT_BORDER_COLOR = Color.BLACK; private static final int DEFAULT_FILL_COLOR = Color.TRANSPARENT; private static final boolean DEFAULT_BORDER_OVERLAY = false; private final RectF mDrawableRect = new RectF(); private final RectF mBorderRect = new RectF(); private final Matrix mShaderMatrix = new Matrix(); private final Paint mBitmapPaint = new Paint(); private final Paint mBorderPaint = new Paint(); private final Paint mFillPaint = new Paint(); private int mBorderColor = DEFAULT_BORDER_COLOR; private int mBorderWidth = DEFAULT_BORDER_WIDTH; private int mFillColor = DEFAULT_FILL_COLOR; private Bitmap mBitmap; private BitmapShader mBitmapShader; private int mBitmapWidth; private int mBitmapHeight; private float mDrawableRadius; private float mBorderRadius; private ColorFilter mColorFilter; private boolean mReady; private boolean mSetupPending; private boolean mBorderOverlay; public CircleImageView(Context context) { super(context); init(); } public CircleImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_civ_border_width, DEFAULT_BORDER_WIDTH); mBorderColor = a.getColor(R.styleable.CircleImageView_civ_border_color, DEFAULT_BORDER_COLOR); mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_civ_border_overlay, DEFAULT_BORDER_OVERLAY); mFillColor = a.getColor(R.styleable.CircleImageView_civ_fill_color, DEFAULT_FILL_COLOR); a.recycle(); init(); } private void init() { super.setScaleType(SCALE_TYPE); mReady = true; if (mSetupPending) { setup(); mSetupPending = false; } } @Override public ScaleType getScaleType() { return SCALE_TYPE; } @Override public void setScaleType(ScaleType scaleType) { if (scaleType != SCALE_TYPE) { throw new IllegalArgumentException(String.format(\"ScaleType %s not supported.\", scaleType)); } } @Override public void setAdjustViewBounds(boolean adjustViewBounds) { if (adjustViewBounds) { throw new IllegalArgumentException(\"adjustViewBounds not supported.\"); } } @Override protected void onDraw(Canvas canvas) { if (mBitmap == null) { return; } if (mFillColor != Color.TRANSPARENT) { canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mDrawableRadius, mFillPaint); } canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mDrawableRadius, mBitmapPaint); if (mBorderWidth != 0) { canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mBorderRadius, mBorderPaint); } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); setup(); } public int getBorderColor() { return mBorderColor; } public void setBorderColor(int borderColor) { if (borderColor == mBorderColor) { return; } mBorderColor = borderColor; mBorderPaint.setColor(mBorderColor); invalidate(); } public void setBorderColorResource(int borderColorRes) { setBorderColor(getContext().getResources().getColor(borderColorRes)); } public int getFillColor() { return mFillColor; } public void setFillColor(int fillColor) { if (fillColor == mFillColor) { return; } mFillColor = fillColor; mFillPaint.setColor(fillColor); invalidate(); } public void setFillColorResource(int fillColorRes) { setFillColor(getContext().getResources().getColor(fillColorRes)); } public int getBorderWidth() { return mBorderWidth; } public void setBorderWidth(int borderWidth) { if (borderWidth == mBorderWidth) { return; } mBorderWidth = borderWidth; setup(); } public boolean isBorderOverlay() { return mBorderOverlay; } public void setBorderOverlay(boolean borderOverlay) { if (borderOverlay == mBorderOverlay) { return; } mBorderOverlay = borderOverlay; setup(); } @Override public void setImageBitmap(Bitmap bm) { super.setImageBitmap(bm); mBitmap = bm; setup(); } @Override public void setImageDrawable(Drawable drawable) { super.setImageDrawable(drawable); mBitmap = getBitmapFromDrawable(drawable); setup(); } @Override public void setImageResource(int resId) { super.setImageResource(resId); mBitmap = getBitmapFromDrawable(getDrawable()); setup(); } @Override public void setImageURI(Uri uri) { super.setImageURI(uri); mBitmap = uri != null ? getBitmapFromDrawable(getDrawable()) : null; setup(); } @Override public void setColorFilter(ColorFilter cf) { if (cf == mColorFilter) { return; } mColorFilter = cf; mBitmapPaint.setColorFilter(mColorFilter); invalidate(); } private Bitmap getBitmapFromDrawable(Drawable drawable) { if (drawable == null) { return null; } if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } try { Bitmap bitmap; if (drawable instanceof ColorDrawable) { bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); } else { bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); } Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } catch (Exception e) { e.printStackTrace(); return null; } } private void setup() { if (!mReady) { mSetupPending = true; return; } if (getWidth() == 0 && getHeight() == 0) { return; } if (mBitmap == null) { invalidate(); return; } mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mBitmapPaint.setAntiAlias(true); mBitmapPaint.setShader(mBitmapShader); mBorderPaint.setStyle(Paint.Style.STROKE); mBorderPaint.setAntiAlias(true); mBorderPaint.setColor(mBorderColor); mBorderPaint.setStrokeWidth(mBorderWidth); mFillPaint.setStyle(Paint.Style.FILL); mFillPaint.setAntiAlias(true); mFillPaint.setColor(mFillColor); mBitmapHeight = mBitmap.getHeight(); mBitmapWidth = mBitmap.getWidth(); mBorderRect.set(0, 0, getWidth(), getHeight()); mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f); mDrawableRect.set(mBorderRect); if (!mBorderOverlay) { mDrawableRect.inset(mBorderWidth, mBorderWidth); } mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f); updateShaderMatrix(); invalidate(); } private void updateShaderMatrix() { float scale; float dx = 0; float dy = 0; mShaderMatrix.set(null); if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { scale = mDrawableRect.height() / (float) mBitmapHeight; dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; } else { scale = mDrawableRect.width() / (float) mBitmapWidth; dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; } mShaderMatrix.setScale(scale, scale); mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top); mBitmapShader.setLocalMatrix(mShaderMatrix); }} attrs123456<declare-styleable name=\"CircleImageView\"> <attr name=\"civ_border_width\" format=\"dimension\" /> <attr name=\"civ_border_color\" format=\"color\" /> <attr name=\"civ_border_overlay\" format=\"boolean\" /> <attr name=\"civ_fill_color\" format=\"color\" /></declare-styleable> 2、RoundImageView123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162/** * 圆形ImageView,可设置最多两个宽度不同且颜色不同的圆形边框。 设置颜色在xml布局文件中由自定义属性配置参数指定 */public class RoundImageView extends ImageView { private int mBorderThickness = 0; private Context mContext; private int defaultColor = 0xFFFFFFFF; // 如果只有其中一个有值,则只画一个圆形边框 private int mBorderOutsideColor = 0; private int mBorderInsideColor = 0; // 控件默认长、宽 private int defaultWidth = 0; private int defaultHeight = 0; public RoundImageView(Context context) { super(context); mContext = context; } public RoundImageView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; setCustomAttributes(attrs); } public RoundImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mContext = context; setCustomAttributes(attrs); } private void setCustomAttributes(AttributeSet attrs) { TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.roundedimageview); mBorderThickness = a.getDimensionPixelSize(R.styleable.roundedimageview_border_thickness, 0); mBorderOutsideColor = a.getColor(R.styleable.roundedimageview_border_outside_color, defaultColor); mBorderInsideColor = a.getColor(R.styleable.roundedimageview_border_inside_color, defaultColor); } @Override protected void onDraw(Canvas canvas) { Drawable drawable = getDrawable(); if (drawable == null) { return; } if (getWidth() == 0 || getHeight() == 0) { return; } this.measure(0, 0); if (drawable.getClass() == NinePatchDrawable.class) return; Bitmap b = ((BitmapDrawable) drawable).getBitmap(); Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true); if (defaultWidth == 0) { defaultWidth = getWidth(); } if (defaultHeight == 0) { defaultHeight = getHeight(); } int radius = 0; if (mBorderInsideColor != defaultColor && mBorderOutsideColor != defaultColor) {// 定义画两个边框,分别为外圆边框和内圆边框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - 2 * mBorderThickness; // 画内圆 drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderInsideColor); // 画外圆 drawCircleBorder(canvas, radius + mBorderThickness + mBorderThickness / 2, mBorderOutsideColor); } else if (mBorderInsideColor != defaultColor && mBorderOutsideColor == defaultColor) {// 定义画一个边框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - mBorderThickness; drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderInsideColor); } else if (mBorderInsideColor == defaultColor && mBorderOutsideColor != defaultColor) {// 定义画一个边框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - mBorderThickness; drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderOutsideColor); } else {// 没有边框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2; } Bitmap roundBitmap = getCroppedRoundBitmap(bitmap, radius); canvas.drawBitmap(roundBitmap, defaultWidth / 2 - radius, defaultHeight / 2 - radius, null); } /** * 获取裁剪后的圆形图片 * * @param radius 半径 */ public Bitmap getCroppedRoundBitmap(Bitmap bmp, int radius) { Bitmap scaledSrcBmp; int diameter = radius * 2; // 为了防止宽高不相等,造成圆形图片变形,因此截取长方形中处于中间位置最大的正方形图片 int bmpWidth = bmp.getWidth(); int bmpHeight = bmp.getHeight(); int squareWidth = 0, squareHeight = 0; int x = 0, y = 0; Bitmap squareBitmap; if (bmpHeight > bmpWidth) {// 高大于宽 squareWidth = squareHeight = bmpWidth; x = 0; y = (bmpHeight - bmpWidth) / 2; // 截取正方形图片 squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, squareHeight); } else if (bmpHeight < bmpWidth) {// 宽大于高 squareWidth = squareHeight = bmpHeight; x = (bmpWidth - bmpHeight) / 2; y = 0; squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, squareHeight); } else { squareBitmap = bmp; } if (squareBitmap.getWidth() != diameter || squareBitmap.getHeight() != diameter) { scaledSrcBmp = Bitmap.createScaledBitmap(squareBitmap, diameter, diameter, true); } else { scaledSrcBmp = squareBitmap; } Bitmap output = Bitmap.createBitmap(scaledSrcBmp.getWidth(), scaledSrcBmp.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(output); Paint paint = new Paint(); Rect rect = new Rect(0, 0, scaledSrcBmp.getWidth(), scaledSrcBmp.getHeight()); paint.setAntiAlias(true); paint.setFilterBitmap(true); paint.setDither(true); canvas.drawARGB(0, 0, 0, 0); canvas.drawCircle(scaledSrcBmp.getWidth() / 2, scaledSrcBmp.getHeight() / 2, scaledSrcBmp.getWidth() / 2, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(scaledSrcBmp, rect, rect, paint); bmp = null; squareBitmap = null; scaledSrcBmp = null; return output; } /** * 边缘画圆 */ private void drawCircleBorder(Canvas canvas, int radius, int color) { Paint paint = new Paint(); /* 去锯齿 */ paint.setAntiAlias(true); paint.setFilterBitmap(true); paint.setDither(true); paint.setColor(color); /* 设置paint的 style 为STROKE:空心 */ paint.setStyle(Paint.Style.STROKE); /* 设置paint的外框宽度 */ paint.setStrokeWidth(mBorderThickness); canvas.drawCircle(defaultWidth / 2, defaultHeight / 2, radius, paint); }} attrs12345<declare-styleable name=\"roundedimageview\"> <attr name=\"border_thickness\" format=\"dimension\" /> <attr name=\"border_inside_color\" format=\"color\" /> <attr name=\"border_outside_color\" format=\"color\"></attr></declare-styleable> 如果用Glide推荐用transForm转换","categories":[],"tags":[{"name":"Android","slug":"Android","permalink":"http://itdais.com/tags/Android/"},{"name":"图片加载","slug":"图片加载","permalink":"http://itdais.com/tags/图片加载/"},{"name":"自定义控件","slug":"自定义控件","permalink":"http://itdais.com/tags/自定义控件/"}]},{"title":"AppCrash崩溃监听","slug":"Crash崩溃监听","date":"2016-08-28T13:06:29.000Z","updated":"2016-08-28T13:06:29.636Z","comments":true,"path":"2016/08/28/Crash崩溃监听/","link":"","permalink":"http://itdais.com/2016/08/28/Crash崩溃监听/","excerpt":"","text":"","categories":[],"tags":[]},{"title":"ScrollView嵌套ListView,GridView,ExpandableListView","slug":"ScrollView嵌套ListView-GridView-ExpandableListView","date":"2016-08-26T12:14:15.000Z","updated":"2016-08-26T12:14:15.392Z","comments":true,"path":"2016/08/26/ScrollView嵌套ListView-GridView-ExpandableListView/","link":"","permalink":"http://itdais.com/2016/08/26/ScrollView嵌套ListView-GridView-ExpandableListView/","excerpt":"","text":"","categories":[],"tags":[]},{"title":"SwipeToRefresh滑动冲突解决","slug":"SwipeToRefresh滑动冲突解决","date":"2016-08-25T13:59:14.000Z","updated":"2016-08-25T14:03:50.159Z","comments":true,"path":"2016/08/25/SwipeToRefresh滑动冲突解决/","link":"","permalink":"http://itdais.com/2016/08/25/SwipeToRefresh滑动冲突解决/","excerpt":"解决SwipeToRefresh嵌套ViewPager等左右滑动和下拉刷新冲突的方案","text":"解决SwipeToRefresh嵌套ViewPager等左右滑动和下拉刷新冲突的方案 自定义SwipeToRefresh12345678910111213141516171819202122232425262728293031323334353637383940import android.content.Context;import android.support.v4.widget.SwipeRefreshLayout;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.ViewConfiguration;/** * 解决SwipeToRefresh嵌套ViewPager等左右滑动和下拉刷新冲突的方案 */public class HorizontalSwipeToRefresh extends SwipeRefreshLayout { private int mTouchSlop; private float mPrevX; public HorizontalSwipeToRefresh(Context context, AttributeSet attrs) { super(context, attrs); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mPrevX = MotionEvent.obtain(event).getX(); break; case MotionEvent.ACTION_MOVE: final float eventX = event.getX(); float xDiff = Math.abs(eventX - mPrevX); if (xDiff > mTouchSlop) { return false; } } return super.onInterceptTouchEvent(event); }}","categories":[],"tags":[{"name":"Android","slug":"Android","permalink":"http://itdais.com/tags/Android/"},{"name":"SwipeToRefresh","slug":"SwipeToRefresh","permalink":"http://itdais.com/tags/SwipeToRefresh/"},{"name":"滑动冲突","slug":"滑动冲突","permalink":"http://itdais.com/tags/滑动冲突/"},{"name":"自定义控件","slug":"自定义控件","permalink":"http://itdais.com/tags/自定义控件/"}]},{"title":"EditText限制输入小数点后两位","slug":"EditText限制输入小数点后两位","date":"2016-07-28T12:37:32.000Z","updated":"2016-08-02T13:21:14.544Z","comments":true,"path":"2016/07/28/EditText限制输入小数点后两位/","link":"","permalink":"http://itdais.com/2016/07/28/EditText限制输入小数点后两位/","excerpt":"实现EditText只能输入小数点后两位的控制,主要是给EditText添加输入监听事件","text":"实现EditText只能输入小数点后两位的控制,主要是给EditText添加输入监听事件 1、设置EditTextEditText设置输入类型为浮点型1android:inputType=\"numberDecimal\" 设置监听1mEditText.addTextChangedListener(new MyTextWatcher()); 2、监听器123456789101112131415161718192021222324252627282930313233343536373839class MyTextWatcher implements TextWatcher{ @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (s.toString().contains(\".\")) { if (s.length() - 1 - s.toString().indexOf(\".\") > 2) { s = s.toString().subSequence(0, s.toString().indexOf(\".\") + 3); mEditText.setText(s); mEditText.setSelection(s.length()); } } if (s.toString().trim().substring(0).equals(\".\")) { s = \"0\" + s; mEditText.setText(s); mEditText.setSelection(2); } if (s.toString().startsWith(\"0\") && s.toString().trim().length() > 1) { if (!s.toString().substring(1, 2).equals(\".\")) { mEditText.setText(s.subSequence(0, 1)); mEditText.setSelection(1); return; } } } @Override public void afterTextChanged(Editable s) { }} 当前已经实现了小数点后两位的控制了 3、拓展实现当我们没有输入小数点,格式化数据为#.00的格式 12345678910111213141516171819202122232425262728//判断是不是浮点型public static boolean isFolat(String value) { boolean bCheckResult = true; try { Float dCheckValue = Float.parseFloat(value); if (dCheckValue instanceof Float == false) { bCheckResult = false; } } catch (NumberFormatException e) { bCheckResult = false; } return bCheckResult; } /** * 格式化字符串 */ public static String formatFloat(String str) { if (isFolat(str)) { DecimalFormat format = new DecimalFormat(\"#0.00\"); return format.format(Double.parseDouble(str)); } else { return str; } }","categories":[],"tags":[{"name":"Android","slug":"Android","permalink":"http://itdais.com/tags/Android/"},{"name":"Widget","slug":"Widget","permalink":"http://itdais.com/tags/Widget/"},{"name":"EditText","slug":"EditText","permalink":"http://itdais.com/tags/EditText/"}]},{"title":"加载Https的图片","slug":"加载Https的图片","date":"2016-07-20T13:25:20.000Z","updated":"2016-07-28T13:04:00.584Z","comments":true,"path":"2016/07/20/加载Https的图片/","link":"","permalink":"http://itdais.com/2016/07/20/加载Https的图片/","excerpt":"本文介绍的是如何在项目中加载已Https为开头的图片,图片加载框架是Glide和UIL,当加载图片时候禁用掉所有的 SSL 证书检查。","text":"本文介绍的是如何在项目中加载已Https为开头的图片,图片加载框架是Glide和UIL,当加载图片时候禁用掉所有的 SSL 证书检查。 UIL加载图片 ImageLoader我们需要自己写一个图片加载替换掉原有的imageDownloader,在application中配置就可以了 在Application中初始化ImageLoader 12345678910111213141516171819202122232425public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); //设置OKHttp 支持https请求 OkHttpUtils.getInstance().setCertificates(); initImageLoader(); } private void initImageLoader() { ImageLoaderConfiguration config = new ImageLoaderConfiguration .Builder(getApplicationContext()) .threadPriority(Thread.NORM_PRIORITY - 2) .denyCacheImageMultipleSizesInMemory() .diskCacheFileNameGenerator(new Md5FileNameGenerator()) //替换允许Https的图片加载 .imageDownloader(new AuthImageDownloader(this)) .tasksProcessingOrder(QueueProcessingType.LIFO).build(); ImageLoader.getInstance().init(config); } } AuthImageDownloader代码 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101import com.nostra13.universalimageloader.core.download.BaseImageDownloader;import java.io.BufferedInputStream;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.security.KeyManagementException;import java.security.NoSuchAlgorithmException;import javax.net.ssl.HostnameVerifier;import javax.net.ssl.HttpsURLConnection;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSession;import javax.net.ssl.SSLSocketFactory;/** * HTTPS的图片加载 */public class AuthImageDownloader extends BaseImageDownloader { private SSLSocketFactory mSSLSocketFactory; public AuthImageDownloader(Context context) { super(context); SSLContext sslContext = sslContextForTrustedCertificates(); mSSLSocketFactory = sslContext.getSocketFactory(); } public AuthImageDownloader(Context context, int connectTimeout, int readTimeout) { super(context, connectTimeout, readTimeout); SSLContext sslContext = sslContextForTrustedCertificates(); mSSLSocketFactory = sslContext.getSocketFactory(); } @Override protected InputStream getStreamFromNetwork(String imageUri, Object extra) throws IOException { URL url = null; try { url = new URL(imageUri); } catch (MalformedURLException e) { } HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(connectTimeout); conn.setReadTimeout(readTimeout); if (conn instanceof HttpsURLConnection) { ((HttpsURLConnection)conn).setSSLSocketFactory(mSSLSocketFactory); ((HttpsURLConnection)conn).setHostnameVerifier((DO_NOT_VERIFY)); } return new BufferedInputStream(conn.getInputStream(), BUFFER_SIZE); } // always verify the host - dont check for certificate final HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }; public SSLContext sslContextForTrustedCertificates() { javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; javax.net.ssl.TrustManager tm = new miTM(); trustAllCerts[0] = tm; SSLContext sc = null; try { sc = SSLContext.getInstance(\"SSL\"); sc.init(null, trustAllCerts, null); //javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); }catch (KeyManagementException e) { e.printStackTrace(); }finally { return sc; } } class miTM implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public boolean isServerTrusted( java.security.cert.X509Certificate[] certs) { return true; } public boolean isClientTrusted( java.security.cert.X509Certificate[] certs) { return true; } public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { return; } public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { return; } }} Glide加载图片Glide加载Https需要自定义Module,并且要整合Okhttp,让okhttp禁用掉所有的 SSL 证书检查。 gradle引用 引用中介绍的比较麻烦,Glide已经提供了Module给我们使用。 1234compile 'com.squareup.okhttp3:okhttp:3.3.1'compile 'com.github.bumptech.glide:glide:3.7.0'/*提供的Module*/compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar' application中初始化 12//让Glide能用HTTPSGlide.get(this).register(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(RetrofitUtils.getOkHttpClient())); 设置证书这个不是必须的,当你没有证书的时候,就不需要获取,如果有就拿到InputStream,传到下面的getOkHttpClient()的方法中 12345try { InputStream input = getAssets().open(\"server.cer\");} catch (IOException e) { e.printStackTrace();} 配置OkHttp允许Https 获取OkHttpClien 123456789101112131415161718/** * 获取OkHttpClient * 设置允许HTTPS * */public static OkHttpClient getOkHttpClient(InputStream... certificates){ SSLSocketFactory sslSocketFactory = HttpsUtils.getSslSocketFactory(certificates, null, null); OkHttpClient.Builder builder = new OkHttpClient().newBuilder(); builder = builder.sslSocketFactory(sslSocketFactory); builder.hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }); return builder.build();} HttpsUtils中可以传递证书进入,如果没有证书就传null 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164import java.io.IOException;import java.io.InputStream;import java.security.KeyManagementException;import java.security.KeyStore;import java.security.KeyStoreException;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import java.security.UnrecoverableKeyException;import java.security.cert.CertificateException;import java.security.cert.CertificateFactory;import java.security.cert.X509Certificate;import javax.net.ssl.HostnameVerifier;import javax.net.ssl.KeyManager;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSession;import javax.net.ssl.SSLSocketFactory;import javax.net.ssl.TrustManager;import javax.net.ssl.TrustManagerFactory;import javax.net.ssl.X509TrustManager;/** * 设置允许Https */public class HttpsUtils{ public static SSLSocketFactory getSslSocketFactory(InputStream[] certificates, InputStream bksFile, String password){ try{ TrustManager[] trustManagers = prepareTrustManager(certificates); KeyManager[] keyManagers = prepareKeyManager(bksFile, password); SSLContext sslContext = SSLContext.getInstance(\"TLS\"); TrustManager trustManager = null; if (trustManagers != null){ trustManager = new MyTrustManager(chooseTrustManager(trustManagers)); } else{ trustManager = new UnSafeTrustManager(); } sslContext.init(keyManagers, new TrustManager[]{trustManager}, new SecureRandom()); return sslContext.getSocketFactory(); } catch (NoSuchAlgorithmException e){ throw new AssertionError(e); } catch (KeyManagementException e){ throw new AssertionError(e); } catch (KeyStoreException e){ throw new AssertionError(e); } } private class UnSafeHostnameVerifier implements HostnameVerifier{ @Override public boolean verify(String hostname, SSLSession session){ return true; } } private static class UnSafeTrustManager implements X509TrustManager{ @Override public void checkClientTrusted(X509Certificate[] chain, String authType)throws CertificateException{} @Override public void checkServerTrusted(X509Certificate[] chain, String authType)throws CertificateException{} @Override public X509Certificate[] getAcceptedIssuers(){ return new X509Certificate[]{}; } } private static TrustManager[] prepareTrustManager(InputStream... certificates){ if (certificates == null || certificates.length <= 0) return null; try{ CertificateFactory certificateFactory = CertificateFactory.getInstance(\"X.509\"); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null); int index = 0; for (InputStream certificate : certificates){ String certificateAlias = Integer.toString(index++); keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate)); try{ if (certificate != null) certificate.close(); } catch (IOException e){ } } TrustManagerFactory trustManagerFactory = null; trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keyStore); TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); return trustManagers; } catch (NoSuchAlgorithmException e){ e.printStackTrace(); } catch (CertificateException e){ e.printStackTrace(); } catch (KeyStoreException e){ e.printStackTrace(); } catch (Exception e){ e.printStackTrace(); } return null; } private static KeyManager[] prepareKeyManager(InputStream bksFile, String password){ try{ if (bksFile == null || password == null) return null; KeyStore clientKeyStore = KeyStore.getInstance(\"BKS\"); clientKeyStore.load(bksFile, password.toCharArray()); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(clientKeyStore, password.toCharArray()); return keyManagerFactory.getKeyManagers(); } catch (KeyStoreException e){ e.printStackTrace(); } catch (NoSuchAlgorithmException e){ e.printStackTrace(); } catch (UnrecoverableKeyException e){ e.printStackTrace(); } catch (CertificateException e){ e.printStackTrace(); } catch (IOException e){ e.printStackTrace(); } catch (Exception e){ e.printStackTrace(); } return null; } private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers){ for (TrustManager trustManager : trustManagers){ if (trustManager instanceof X509TrustManager){ return (X509TrustManager) trustManager; } } return null; } private static class MyTrustManager implements X509TrustManager{ private X509TrustManager defaultTrustManager; private X509TrustManager localTrustManager; public MyTrustManager(X509TrustManager localTrustManager) throws NoSuchAlgorithmException, KeyStoreException{ TrustManagerFactory var4 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); var4.init((KeyStore) null); defaultTrustManager = chooseTrustManager(var4.getTrustManagers()); this.localTrustManager = localTrustManager; } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException{} @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException{ try{ defaultTrustManager.checkServerTrusted(chain, authType); } catch (CertificateException ce){ localTrustManager.checkServerTrusted(chain, authType); } } @Override public X509Certificate[] getAcceptedIssuers(){ return new X509Certificate[0]; } }} 所有代码引入后就可以,Glide就可以加载Https开头的图片了。 引用 完美解决imageloader加载https图片Glide加载HttpsGlide加载Https中文翻译","categories":[],"tags":[{"name":"Android","slug":"Android","permalink":"http://itdais.com/tags/Android/"},{"name":"图片加载","slug":"图片加载","permalink":"http://itdais.com/tags/图片加载/"},{"name":"HTTPS","slug":"HTTPS","permalink":"http://itdais.com/tags/HTTPS/"}]},{"title":"Android ADB端口被占用","slug":"Android ADB端口被占用","date":"2016-07-18T13:45:18.000Z","updated":"2016-07-28T13:04:03.531Z","comments":true,"path":"2016/07/18/Android ADB端口被占用/","link":"","permalink":"http://itdais.com/2016/07/18/Android ADB端口被占用/","excerpt":"最近几天使用android studio1.5.1的时候一直提示错误,一开始没在意,重启就好了.但是总不能一直报错就重启吧,查看下问题原因吧,发现是android adb的端口被占用了。当使用到音乐播放器如酷狗酷我或者使用了豌豆荚、360手机助手等软件时候,是会抢占掉adb的端口的。","text":"最近几天使用android studio1.5.1的时候一直提示错误,一开始没在意,重启就好了.但是总不能一直报错就重启吧,查看下问题原因吧,发现是android adb的端口被占用了。当使用到音乐播放器如酷狗酷我或者使用了豌豆荚、360手机助手等软件时候,是会抢占掉adb的端口的。 解决方法一:杀死占用进程解决方法二:重设adb的端口","categories":[],"tags":[{"name":"Android","slug":"Android","permalink":"http://itdais.com/tags/Android/"},{"name":"BUG","slug":"BUG","permalink":"http://itdais.com/tags/BUG/"}]},{"title":"屏幕管理工具类","slug":"屏幕管理工具类","date":"2016-07-18T13:15:20.000Z","updated":"2016-08-02T13:21:37.458Z","comments":true,"path":"2016/07/18/屏幕管理工具类/","link":"","permalink":"http://itdais.com/2016/07/18/屏幕管理工具类/","excerpt":"提供了dp互转px,sp互转px,获取屏幕宽高,获取状态栏高度、toolbar高度、底部虚拟菜单高度等等。 dp(dip): device independent pixels(设备独立像素).不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA、HVGA和QVGA 推荐使用这个,不依赖像素。 使用dp和sp,系统会根据屏幕密度的变化自动进行转换。如果设置表示长度、高度等属性时可以使用dp。但如果设置字体,需要使用sp。dp是与密度无关,sp除了与密度无关外,还与scale无关。 px: pixels(像素). 不同设备显示效果相同,一般我们HVGA代表320x480像素,这个用的比较多。 sp: scaled pixels(放大像素). 主要用于字体显示best for textsize。","text":"提供了dp互转px,sp互转px,获取屏幕宽高,获取状态栏高度、toolbar高度、底部虚拟菜单高度等等。 dp(dip): device independent pixels(设备独立像素).不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA、HVGA和QVGA 推荐使用这个,不依赖像素。 使用dp和sp,系统会根据屏幕密度的变化自动进行转换。如果设置表示长度、高度等属性时可以使用dp。但如果设置字体,需要使用sp。dp是与密度无关,sp除了与密度无关外,还与scale无关。 px: pixels(像素). 不同设备显示效果相同,一般我们HVGA代表320x480像素,这个用的比较多。 sp: scaled pixels(放大像素). 主要用于字体显示best for textsize。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277import android.app.Activity;import android.content.Context;import android.content.res.Configuration;import android.content.res.Resources;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.Rect;import android.util.DisplayMetrics;import android.util.Log;import android.util.TypedValue;import android.view.View;import android.view.Window;public class DensityUtils { private static final float DOT_FIVE = 0.5f; /** * dip to px * * @param context * @param dip * @return */ public static int dip2px(Context context, float dip) { float density = getDensity(context); return (int) (dip * density + DensityUtils.DOT_FIVE); } /** * px to dip * * @param context * @param px * @return */ public static int px2dip(Context context, float px) { float density = getDensity(context); return (int) (px / density + DOT_FIVE); } /** * 将px值转换为sp值,保证文字大小不变 * * @param pxValue * @param pxValue * (DisplayMetrics类中属性scaledDensity) * @return */ public static int px2sp(Context context, float pxValue) { final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int) (pxValue / fontScale + 0.5f); } /** * 将sp值转换为px值,保证文字大小不变 * * @param spValue * @param spValue * (DisplayMetrics类中属性scaledDensity) * @return */ public static int sp2px(Context context, float spValue) { final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int) (spValue * fontScale + 0.5f); } private static DisplayMetrics sDisplayMetrics; /** * get screen width * * @param context * @return */ public static int getDisplayWidth(Context context) { initDisplayMetrics(context); return sDisplayMetrics.widthPixels; } /** * get screen height * * @param context * @return */ public static int getDisplayHeight(Context context) { initDisplayMetrics(context); return sDisplayMetrics.heightPixels; } /** * get screen density * * @param context * @return */ public static float getDensity(Context context) { initDisplayMetrics(context); return sDisplayMetrics.density; } /** * get screen density dpi * * @param context * @return */ public static int getDensityDpi(Context context) { initDisplayMetrics(context); return sDisplayMetrics.densityDpi; } /** * init display metrics * * @param context */ private static synchronized void initDisplayMetrics(Context context) { sDisplayMetrics = context.getResources().getDisplayMetrics(); } /** * is landscape * * @param context * @return */ public static boolean isLandscape(Context context) { return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; } /** * is portrait * * @param context * @return */ public static boolean isPortrait(Context context) { return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; } public static int getActvieHeight(Activity activity){ Dimension dimen = new Dimension(); // 用户绘制区域 Rect outRect = new Rect(); activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(outRect); dimen.mWidth = outRect.width() ; dimen.mHeight = outRect.height(); // end return dimen.mHeight; } /** * 获得状态栏的高度 * * @param activity * @return */ public static int getStatusHeight(Activity activity) {// Rect frame = new Rect();// activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);// int statusBarHeight = frame.top;// Log.d("111","statusBarHeight"+statusBarHeight); int statusHeight = -1; try { Class<?> clazz = Class.forName("com.android.internal.R$dimen"); Object object = clazz.newInstance(); int height = Integer.parseInt(clazz.getField("status_bar_height") .get(object).toString()); statusHeight = activity.getResources().getDimensionPixelSize(height); } catch (Exception e) { e.printStackTrace(); } return statusHeight; } public int getNavigationBarHeight(Activity activity) { Resources resources = activity.getResources(); int resourceId = resources.getIdentifier("navigation_bar_height","dimen", "android"); int height = resources.getDimensionPixelSize(resourceId); Log.v("dbw", "Navi height:" + height); return height; } public static int getActionBarHeight(Context context) { TypedValue tv = new TypedValue(); if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { int actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics()); return actionBarHeight; }else{ return 0; } } /** * get toolbar height * @param context * @return */ public static int getToolbarHeight(Context context) { final TypedArray styledAttributes = context.getTheme().obtainStyledAttributes( new int[]{android.R.attr.actionBarSize}); int toolbarHeight = (int) styledAttributes.getDimension(0, 0); styledAttributes.recycle(); return toolbarHeight; } private int getTitleHeight(Activity activity) { int contentTop = activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop(); //statusBarHeight是上面状态栏的高度 int titleBarHeight = contentTop - getStatusHeight(activity); return titleBarHeight; } private int getActionBarSizeHeight(Activity activity) { return activity.getActionBar().getHeight(); } public static class Dimension { public int mWidth ; public int mHeight ; public Dimension(){} } /** * 获取当前屏幕截图,包含状态栏 * * @param activity * @return */ public static Bitmap snapShotWithStatusBar(Activity activity) { View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bmp = view.getDrawingCache(); int width = getDisplayWidth(activity); int height = getDisplayHeight(activity); Bitmap bp = null; bp = Bitmap.createBitmap(bmp, 0, 0, width, height); view.destroyDrawingCache(); return bp; } /** * 获取当前屏幕截图,不包含状态栏 * * @param activity * @return */ public static Bitmap snapShotWithoutStatusBar(Activity activity) { View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bmp = view.getDrawingCache(); Rect frame = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); int statusBarHeight = frame.top; int width = getDisplayWidth(activity); int height = getDisplayHeight(activity); Bitmap bp = null; bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight); view.destroyDrawingCache(); return bp; }}","categories":[{"name":"archives","slug":"archives","permalink":"http://itdais.com/categories/archives/"}],"tags":[{"name":"Android","slug":"Android","permalink":"http://itdais.com/tags/Android/"},{"name":"屏幕","slug":"屏幕","permalink":"http://itdais.com/tags/屏幕/"},{"name":"工具类","slug":"工具类","permalink":"http://itdais.com/tags/工具类/"}]},{"title":"通用验证工具类","slug":"通用验证工具类","date":"2016-07-06T15:02:10.000Z","updated":"2016-07-28T13:04:02.041Z","comments":true,"path":"2016/07/06/通用验证工具类/","link":"","permalink":"http://itdais.com/2016/07/06/通用验证工具类/","excerpt":"本文收集了一些常用的验证方法,如手机号码验证、银行卡验证等,以后会不定期的更新","text":"本文收集了一些常用的验证方法,如手机号码验证、银行卡验证等,以后会不定期的更新 1、手机号码验证123456789101112/** * 判断手机格式是否正确 * 表示以1开头,第二位可能是3/4/5/7/8等的任意一个,在加上后面的\\d表示数字[0-9]的9位,总共加起来11位结束 * * @return true 是手机号码 */public static boolean isMobile(String mobiles){ Pattern p = Pattern.compile(\"^1[3|4|5|7|8]\\\\d{9}$\"); Matcher m = p.matcher(mobiles); return m.matches();} 2、中文验证12345678910/** * 检查是否全部是中文 * @return true 全是中文 */public static boolean isChinaise(String body){ Pattern p = Pattern.compile(\"^[\\\\u4e00-\\\\u9fa5]+\"); Matcher m = p.matcher(body); return m.matches();} 3、银行卡校验Luhn检验数字算法(Luhn Check Digit Algorithm),也叫做模数10公式,是一种简单的算法,用于验证银行卡、信用卡号码的有效性的算法。对所有大型信用卡公司发行的信用卡都起作用,这些公司包括美国Express、护照、万事达卡、Discover和用餐者俱乐部等。这种算法最初是在20世纪60年代由一组数学家制定,现在Luhn检验数字算法属于大众,任何人都可以使用它。 算法:将每个奇数加倍和使它变为单个的数字,如果必要的话通过减去9和在每个偶数上加上这些值。如果此卡要有效,那么,结果必须是10的倍数。 该校验的过程:1、从卡号最后一位数字开始,逆向将奇数位(1、3、5等等)相加。2、从卡号最后一位数字开始,逆向将偶数位数字,先乘以2(如果乘积为两位数,则将其减去9),再求和。3、将奇数位总和加上偶数位总和,结果应该可以被10整除。12345678910111213141516171819202122232425262728293031323334353637383940/** * 校验银行卡卡号 * * @param cardId * @return */ public static boolean isBankCard(String cardId) { char bit = getBankCardCheckCode(cardId.substring(0, cardId.length() - 1)); if (bit == 'N') { return false; } return cardId.charAt(cardId.length() - 1) == bit; } /** * 从不含校验位的银行卡卡号采用 Luhn 校验算法获得校验位 * * @param nonCheckCodeCardId * @return */ public static char getBankCardCheckCode(String nonCheckCodeCardId) { if (nonCheckCodeCardId == null || nonCheckCodeCardId.trim().length() == 0 || !nonCheckCodeCardId.matches(\"\\\\d+\")) { //如果传的不是数据返回N return 'N'; } char[] chs = nonCheckCodeCardId.trim().toCharArray(); int luhmSum = 0; for (int i = chs.length - 1, j = 0; i >= 0; i--, j++) { int k = chs[i] - '0'; if (j % 2 == 0) { k *= 2; k = k / 10 + k % 10; } luhmSum += k; } return (luhmSum % 10 == 0) ? '0' : (char) ((10 - luhmSum % 10) + '0'); }","categories":[],"tags":[{"name":"Android","slug":"Android","permalink":"http://itdais.com/tags/Android/"},{"name":"工具类","slug":"工具类","permalink":"http://itdais.com/tags/工具类/"}]},{"title":"Hello World","slug":"hello-world","date":"2016-07-04T15:05:44.269Z","updated":"2016-07-04T15:05:44.270Z","comments":true,"path":"2016/07/04/hello-world/","link":"","permalink":"http://itdais.com/2016/07/04/hello-world/","excerpt":"","text":"Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. Quick StartCreate a new post1$ hexo new \"My New Post\" More info: Writing Run server1$ hexo server More info: Server Generate static files1$ hexo generate More info: Generating Deploy to remote sites1$ hexo deploy More info: Deployment","categories":[],"tags":[]}]}