部分笔记: canvas, permission , softInput , cardview

来源:互联网 发布:什么是网络爬虫 编辑:程序博客网 时间:2024/06/17 17:33

图片上面两个是圆角,下面不是圆角

1,使用自定义Imageview ,在onDraw里面实现

    `    @Override    protected void onDraw(Canvas canvas) {        BitmapShader shader;        BitmapDrawable bitmapDrawable = (BitmapDrawable) getDrawable();        shader = new BitmapShader(bitmapDrawable.getBitmap(),                Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);        //设置映射否则图片显示不全        RectF rect = new RectF(0.0f, 0.0f, getWidth(), getHeight() + yRadius);        int width = bitmapDrawable.getBitmap().getWidth();        int height = bitmapDrawable.getBitmap().getHeight() + (int) yRadius;        RectF src = new RectF(0.0f, 0.0f, width, height);        Matrix matrix = new Matrix();        matrix.setRectToRect(src, rect, Matrix.ScaleToFit.CENTER);        shader.setLocalMatrix(matrix);        Paint paint = new Paint();        paint.setAntiAlias(true);        paint.setShader(shader);        //根据图片圆角矩形的半径进行裁剪        canvas.clipRect(new Rect(0, 0, (int) (rect.right), (int) (rect.bottom - yRadius)));        //这样就把下面的部分剪裁掉了,只剩下上面两个圆角了        canvas.drawRoundRect(rect, xRadius, yRadius, paint);    }    `同理,可以实现左边右边上面下面四种建材,缺点是只能两两实现圆角剪裁而不能自定义某一个角

ps:这个了解就好, 不适用, 未来的时候建议使用 glide 学习中的使用完美的剪裁方案, 方便快捷

关于Cavans的方法:

Canvas():创建一个空的画布,可以使用setBitmap()方法来设置绘制的具体画布;Canvas(Bitmap bitmap):以bitmap对象创建一个画布,则将内容都绘制在bitmap上,bitmap不得为null;Canvas(GL gl):在绘制3D效果时使用,与OpenGL有关;drawColor:设置画布的背景色;setBitmap:设置具体的画布;clipRect:设置显示区域,即设置裁剪区;isOpaque:检测是否支持透明;rotate:旋转画布;canvas.drawRect(RectF,Paint)方法用于画矩形,第一个参数为图形显示区域,第二个参数为画笔,设置好图形显示区域Rect和画笔Paint后,即可画图;canvas.drawRoundRect(RectF, float, float, Paint) 方法用于画圆角矩形,第一个参数为图形显示区域,第二个参数和第三个参数分别是水平圆角半径和垂直圆角半径。canvas.drawLine(startX, startY, stopX, stopY, paint):前四个参数的类型均为float,最后一个参数类型为Paint。表示用画笔paint从点(startX,startY)到点(stopX,stopY)画一条直线;canvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint):第一个参数oval为RectF类型,即圆弧显示区域,startAngle和sweepAngle均为float类型,分别表示圆弧起始角度和圆弧度数,3点钟方向为0度,useCenter设置是否显示圆心,boolean类型,paint为画笔;canvas.drawCircle(float,float, float, Paint)方法用于画圆,前两个参数代表圆心坐标,第三个参数为圆半径,第四个参数是画笔;Rect(int left,int top,int right,int bottom)left          矩形左上角X坐标值top          矩形左上角Y坐标值right          矩形右下角X坐标值bottom          矩形右下角Y坐标值

ps:这个了解即可, 如果未来需要深入学习可以查看 爱哥 的 自定义控件其实很简单系列

2,关于Android的权限结构: 危险权限(即需要不断申请的权限)

权限组位于 #Manifest#permission_group 中

1,日历权限组: CALENDAR “android.permission-group.CALENDAR”

读取日历 READ_CALENDAR “android.permission.READ_CALENDAR”

编辑日历(比如添加行程等) WRITE_CALENDAR “android.permission.WRITE_CALENDAR”

2,摄像机组: CAMERA “android.permission-group.CAMERA”

打开摄像机 CAMERA “android.permission.CAMERA”

3,联系人组: CONTACTS “android.permission-group.CONTACTS”

读取联系人 READ_CONTACTS “android.permission.READ_CONTACTS”

修改联系人(增加删除联系人) WRITE_CONTACTS “android.permission.WRITE_CONTACTS”

4,麦克风组: MICROPHONE “android.permission-group.MICROPHONE”

打开麦克风 RECORD_AUDIO “android.permission.RECORD_AUDIO”

5,手机使用组: PHONE “android.permission-group.PHONE”

读取手机状态 READ_PHONE_STATE “android.permission.READ_PHONE_STATE”

拨打电话(直接自动拨打,不是跳转到拨打电话界面,任何跳转都不需要权限,如跳转到打电话界面和发送短信界面) CALL_PHONE “android.permission.CALL_PHONE”

读取通话记录 READ_CALL_LOG “android.permission.READ_CALL_LOG”

修改通话记录(添加和删除通话记录,如黑名单中挂断电话后还把该通话记录删除) WRITE_CALL_LOG “android.permission.WRITE_CALL_LOG”

6,传感器组: SENSORS “android.permission-group.SENSORS”

使用身体传感器(其他传感器没题) BODY_SENSORS “android.permission.BODY_SENSORS”

7,短信组: SMS “android.permission-group.SMS”

发送短信(直接发送短信) SEND_SMS “android.permission.SEND_SMS”

接收短信 RECEIVE_SMS “android.permission.RECEIVE_SMS”

读取短信 READ_SMS “android.permission.READ_SMS”

彩信相关 RECEIVE_MMS “android.permission.RECEIVE_MMS”

8,sd卡组: STORAGE “android.permission-group.STORAGE”

读取sd卡数据 READ_EXTERNAL_STORAGE “android.permission.READ_EXTERNAL_STORAGE”

向sd卡写数据 WRITE_EXTERNAL_STORAGE “android.permission.WRITE_EXTERNAL_STORAGE”

9,位置组: LOCATION “android.permission-group.LOCATION”

获取精确位置 ACCESS_FINE_LOCATION “android.permission.ACCESS_FINE_LOCATION”

获取大致位置 ACCESS_COARSE_LOCATION “android.permission.ACCESS_COARSE_LOCATION”

3,关于Fragment的小坑(不能叫坑,只是我自己的问题,记录下来是为了让自己以后不犯错)

一般在newInstence中的 fragment是 static的, 所以在合适的时机必须调用 fragment=null ,来销毁该fragment, 否则下次调用的时候该fragment会使用,但是该fragment的各种状态却还在没有重置

4,弹出dialog的时候弹出软键盘

背景: 项目中任何界面都是 默认不弹出软键盘的,所以 在baseactivity中有 开启新界面的配置了不弹出软键盘(在onCreate()之前调用:)

//有EditView的界面,默认不弹窗软键盘getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

但是在支付界面是需要输入支付密码的, 这个密码用的是dialog, 需求需要在这个dialog弹出的时候自动弹出软键盘,所以这个时候是需要对软键盘进行处理的,具体处理方法如下:

在dialog的oncreate方法中添加

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

如果使用的alertDialog,可以

AlertDialog.Builder builder = new Builder(context);final View view = View.inflate(context, R.layout.dialog_enter_pwd, null);builder.setView(view);builder.setCancelable(false);final AlertDialog dialog = builder.show();dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

至此,我的问题就解决了

其他的方法如:

1,在调用dialog之前在activity中调用

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

2,在调用完毕后调用

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

总之: SOFT_INPUT_STATE_ALWAYS_VISIBLE , 和 SOFT_INPUT_STATE_VISIBLE 都试试.

PS:

1, activity的getWindow 是获取该activity依赖的窗口, 如果当前activity不可见,则值为null,在当前activity调用该方法得到的Window为当前的窗口

final void attach(Context context, ActivityThread aThread,        Instrumentation instr, IBinder token, int ident,        Application application, Intent intent, ActivityInfo info,        CharSequence title, Activity parent, String id,        NonConfigurationInstances lastNonConfigurationInstances,        Configuration config, String referrer, IVoiceInteractor voiceInteractor) {    attachBaseContext(context);    ....    //创建对应的Window 并设置callback, 其实为PhoneWindow    mWindow = new PhoneWindow(this);    mWindow.setCallback(this);    mWindow.setOnWindowDismissedCallback(this);    ....    // 设置Window的WindowManager, 对Window的mWindowManager赋值,    // 事实上, Window中 并未使用传递进去的windowManager, 而是在此方法中 调用WindowManagerImpl.createLocalWindowManager 重新创建了一个    mWindow.setWindowManager(            (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),            mToken, mComponent.flattenToString(),            (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);    if (mParent != null) {        mWindow.setContainer(mParent.getWindow());    }    // 把window对象中的 windowManager 关联到 Activity的 mWindowManager    mWindowManager = mWindow.getWindowManager();    ...  }

Activity创建之后, 在ActivityThread中 调用 Activity#attach, 进行一些初始化操作,在Activity#attach中, 创建了一个PhoneWindow对象,这个PhoneWindow就是getWindow中得到的window

2, dialog的getWindow 也是获取该dialog创建时所new 出来的phonewindow窗口, 如果当前activity不可见,则值为null,所以dialog调用该方法和activity中调用该方法得到的window是不一样的…不一样….不一样

Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {    ......    // 用getSystemService获取 WindowManger实例    mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);    // 直接创建一个 PhoneWindow的实例    final Window w = new PhoneWindow(mContext);    mWindow = w;    w.setCallback(this);    w.setOnWindowDismissedCallback(this);    w.setWindowManager(mWindowManager, null, null);    w.setGravity(Gravity.CENTER);    mListenersHandler = new ListenersHandler(this);}

代码很明显, 首先获取windowManager实例, 然后创建window对象,然后在设置callback,对PhoneWindow的实例设置WindowManager;(这里有一点和Activity不同, Activity是调用Window的setWindowManager后, 把Window对应的WindowManger获取,然后赋值给自己的变量Activity#mWindowManger, 而dialog没这个操作; dialog对应的Window对象,就只是传入的Context实例去getSystemService所得); 这个PhoneWindow就是getWindow中得到的window

所以他们获取到的window是不一样的

activity中window的地址为:com.android.internal.policy.PhoneWindow@595fa83dialog中window的地址为:com.android.internal.policy.PhoneWindow@960ec5c

很明显不一样

可参考Activity和dialog的窗口添加源码分析

1, Window是一个抽象类, 具体的实现是PhoneWindow

2,android系统中, 每个界面,对应着一个window; 但其实在android系统中window也是一个抽象的概率,它是以view的形式存在; 在使用中, 无法直接访问Window, 只能通过WindowManager才能访问Window; 每个Window都对应一个View和一个ViewRootImpl, ViewRootImpl是连接Window和WMS的桥梁, WMS的一些消息,通过ViewRootImpl转发给View;

3, WindowManager继承自ViewManager(间接证明Window其实对应的是View?),常用的只有三个方法:addView、updateView和removeView

4,各种Window的不同, 主要是 token及type的不同

5,app中控制window, 是通过WindowManager.LayoutParams去控制, eg: 通过x,y,gravity去控制位置…

CardView使用

参考资料: CardView的使用

1,基本使用

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"        xmlns:cardview="http://schemas.android.com/apk/res-auto"       cardview:cardElevation="5dp"       cardview:cardCornerRadius="6dp"       android:layout_width="match_parent"       android:layout_height="match_parent"></android.support.v7.widget.CardView>

cardview:cardElevation 表示cardView 的阴影的 高度

cardview:cardCornerRadius 表示cardView 的圆角的边缘弧度数

2,拓展属性介绍

cardBackgroundColor   : 设置CardView的背景颜色cardMaxElevation   : 设置最大高度cardUseCompatPadding :设置内边距cardPreventCornerOverlap : 是否添加内边距,为了防止卡片内容和边角的重叠contentPadding : 设置CardView边界跟内部的间距contentPaddingLeft :设置CardView边界跟内部的左间距contentPaddingRight:设置CardView边界跟内部的右间距contentPaddingTop:设置CardView边界跟内部的上间距contentPaddingBottom:设置CardView边界跟内部的下间距

3,一些问题和一些实现

1,在API21(5.0) 以上,使用起来没有问题;

2,在API21以下,在CardView 与内部view会有默认的边距, 图 , 原因是因为 在API21以下,为了防止内容与CardView 重叠, 默认使用cardPreventCornerOverlap =true 使会有默认边距 ,解决这个问题, 只需要添加代码 cardPreventCornerOverlap =false 即可;

3,CardView设置不了与屏幕的间距, 只需要在CardView外面再套一层布局 再设置CardView的margin值即可;

4,CardView继承于FrameLayout 可以作为根布局来使用, 具有FrameLayout的一切特点,但是要注意第三点提到的问题,同时也要注意子View的位置;

5,去除阴影 card_view:cardElevation=”0dp” 即可;

6,设置点击水波纹效果 android:foreground=”?attr/selectableItemBackground” 但是在5.0以下就没有效果;

7,实现Material Design 点击阴影效果 需要借助5.0的属性 android:stateListAnimator, 5.0以下没有效果

创建一个Z轴方向的动画,设置属性为android:stateListAnimator=”@anim/xxx

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <item android:state_enabled="true" android:state_pressed="true">        <objectAnimator            android:duration="@android:integer/config_shortAnimTime"            android:propertyName="translationZ"            android:valueTo="@dimen/touch_raise"            android:valueType="floatType" />    </item>    <item>        <objectAnimator            android:duration="@android:integer/config_shortAnimTime"            android:propertyName="translationZ"            android:valueTo="0dp"            android:valueType="floatType" />    </item></selector>