开发笑话和游戏等一系列app的知识点总结4

152:通过setOnTouchListener来给imageview画圆,canvas.scale这一步很重要,不然画出来的圆不准。

 paint = new Paint();
        paint.setColor(Color.RED);
        image.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        bitmap = ConvertUtils.drawable2Bitmap(image.getDrawable()).copy(Bitmap.Config.ARGB_8888, true);
                        Canvas canvas = new Canvas(bitmap);
                        canvas.scale(canvas.getWidth()/(float) image.getWidth(),canvas.getHeight()/(float) image.getHeight());
                        canvas.drawCircle(event.getX(),event.getY(),ConvertUtils.dp2px(CeShiActivity.this, 10), paint);
                        image.setImageBitmap(bitmap);
                        break;
                }
                return false;
            }
        });

153:代码中设置textview字体加粗,就一句代码

textView.setTypeface(Typeface.DEFAULT_BOLD);

154:view中有个draw方法,参数是canvas对象,可以先创建一个bitmap,然后将bitmap作为canvas的画布,最后用view的draw方法将view上面的视图画到canvas上,然后就可以给任意的view制作截图了,代码如下所示:(注意要给TextView设置background才能看到文字和背景,所有的view都可以截图)(已记录)

 textView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        bitmap = Bitmap.createBitmap(textView.getWidth(),textView.getHeight(), Bitmap.Config.ARGB_8888);
                        Canvas canvas = new Canvas(bitmap);
                        textView.draw(canvas);
                        canvas.drawCircle(event.getX(),event.getY(),ConvertUtils.dp2px(CeShiActivity.this, 10), paint);
                        ImageUtil.saveBitmap(Environment.getExternalStorageDirectory()+"/a.jpeg",bitmap);
                        break;
                }
                return false;
            }
        });

webview的代码同上:

    webview.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        bitmap = Bitmap.createBitmap(webview.getWidth(),webview.getHeight(), Bitmap.Config.ARGB_8888);
                        Canvas canvas = new Canvas(bitmap);
                        webview.draw(canvas);
                        canvas.drawCircle(event.getX(),event.getY(),ConvertUtils.dp2px(CeShiActivity.this, 10), paint);
                        ImageUtil.saveBitmap(Environment.getExternalStorageDirectory()+"/a.jpeg",bitmap);
                        break;
                }
                return false;
            }
        });

155:Picture的用法

    Picture picture=new Picture();
        Canvas canvas=picture.beginRecording(200,200);//开始绘制
        Paint paint=new Paint();
        paint.setColor(Color.RED);
        canvas.drawCircle(100,100,50,paint);
        picture.endRecording();//结束绘制
        bitmap = Bitmap.createBitmap(picture.getWidth(),picture.getHeight(), Bitmap.Config.ARGB_8888);//创建bitmap,作为canvas的画布
        Canvas canvas1=new Canvas(bitmap);
        picture.draw(canvas1);//将picture上的内容绘制到canvas的画布上
        ImageUtil.saveBitmap(Environment.getExternalStorageDirectory()+"/a.jpeg",bitmap);

156:记录一个异常,在使用SlidingTabLayout时出现卡顿的原因是因为应该用getChildFragmentManager了,因为是在fragment中嵌套了fragment,用SlidingTabLayout的setViewPager(homeViewpager, strings);不要用setViewPager(homeViewpager, strings, activity, list);

157:java.lang.IllegalStateException: FragmentManager is already executing transactions解决方法

https://blog.csdn.net/q1406689423/article/details/66973555

158:scroller的用法

 @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                scroller.startScroll(100, 100, -200, -200, 5000);//x和y的变化量=初始坐标-最终坐标,x的变化量为负表示向右移,y的变化量为负表示向下移
                invalidate();
                break;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if (scroller.computeScrollOffset()) {
            ((View) getParent()).scrollTo(scroller.getCurrX(), scroller.getCurrY());
            invalidate();
        }
    }

159:当你给activity在Androidmanifest中设置了android:launchMode="singleTask"后,你按了home键之后,再回到app中,你会发现其他activity已经被关闭了

160:如果在没有用懒加载的情况下,系统会将viewpager的所有fragment中的数据都获取到之后才会展示出来,因此如果不用懒加载的话,而且fragment还特别多的话会非常卡。

161:系统自带的ListView就可以添加头布局和尾布局,但是添加了头和尾之后,系统会将BaseAdapter转换为HeaderViewListAdapter,要刷新适配器的话,需要再将HeaderViewListAdapter转换为BaseAdapter。

https://1028826685.iteye.com/blog/1464489

162:ScrollView嵌套RecyclerView时只显示一行元素的解决方法:

用NestedScrollView代替ScrollView,然后设置RecyclerView的属性nestedScrollingEnabled="false",最后RecyclerView的item的高度必须是具体的值才行,不能是match_parent。

163:两种滚动的方式:

第一种:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                if (!scroller.isFinished()) {
                    scroller.abortAnimation();
                }
                int deltaY = (yLater - y)*20;
                scroller.startScroll(0, getScrollY(), 0, deltaY);
                invalidate();
                break;
        }
        yLater = y;
        return true;
    } 
 @Override
    public void computeScroll() {
        Log.e("computeScroll", "computeScroll: " + scroller.getCurrX() + "," +      scroller.getCurrY());
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.getCurrX(), scroller.getCurrY());
            invalidate();
        }
    }

第二种:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                if (!scroller.isFinished()) {
                    scroller.abortAnimation();
                }
                int deltaY = (yLater - y);
                scrollBy(0,deltaY);
                invalidate();
                break;
        }
        yLater = y;
        return true;
    } 

心得:在Android中画布是无限大的,view的大小是显示画布的区域,每个view都在各自的画布上面,但是画布之间有这父子关系,父画布上移动自己的画布就相当于在移动所有与父画布相关联的子画布,并且子画布的显示范围受父画布的显示范围影响,超出父画布的显示范围子画布将不会被显示,层层画布叠在一起,每个view的大小和位置就是各自在各自画布中要显示的大小和位置。scrollTo和scrollBy是移动了画布的位置,而不是view的位置。如果是列表类型的viewgroup,比如listview,gridview,recyclerview是不能单纯的用scrollTo和scrollBy来移动内容的,因为它们都有自己的复用机制。

getScrollY()获取到的是子view的左上角相对于父view的左上角(也就是(0,0)点)的y坐标的变化量(父view的左上角的纵坐标(也就是(0,0)点)-子view的左上角的当前纵坐标),变化量为正表示向上划,为负表示向下划。getScrollX()同理。另外滚动后要调用invalidate(),目的是为了调用view的onDraw方法来重新绘制view的布局,这样才能及时更新view的位置。

scroller.startScroll方法的第三个参数和第四个参数

 * @param dx Horizontal distance to travel. Positive numbers will scroll the
 *        content to the left.
 * @param dy Vertical distance to travel. Positive numbers will scroll the
 *        content up.

第三个参数如果是正数表示向左滑动,第四个参数如果是正数表示向上滑动。当然也可以根据:位置变化量=开始位置-最终位置来推出来。

VelocityTracker的使用,最终通过scroller来实现平滑滚动。

   @Override
    public boolean onTouchEvent(MotionEvent event) {
        int y = (int) event.getY();
        if (velocityTracker == null)
            velocityTracker = VelocityTracker.obtain();
        velocityTracker.addMovement(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                if (!scroller.isFinished()) {
                    scroller.abortAnimation();
                }
                int deltaY = (yLater - y);
                scrollBy(0, deltaY);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                velocityTracker.computeCurrentVelocity(1000);
                if (Math.abs(velocityTracker.getYVelocity()) > 8000) {
                    if (velocityTracker.getYVelocity() > 0)
                        scroller.startScroll(0, getScrollY(), 0, -300, 1000);
                    else
                        scroller.startScroll(0, getScrollY(), 0, 300, 1000);
                    invalidate();
                }
                velocityTracker.recycle();
                velocityTracker = null;
                break;
        }
        yLater = y;
        return true;
    }

    @Override
    public void computeScroll() {
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.getCurrX(), scroller.getCurrY());
            invalidate();
        }
    }

164:利用Scroller和VelocityTracker将LinearLayout改造成ScrollerView

public class MyScrollView extends LinearLayout {
    private Scroller scroller;
    private int yLater;
    private VelocityTracker velocityTracker;

    public MyScrollView(Context context) {
        this(context, null, 0);

    }

    public MyScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    private void init(Context context) {
        scroller = new Scroller(context);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int y = (int) event.getY();
        if (velocityTracker == null)
            velocityTracker = VelocityTracker.obtain();
        velocityTracker.addMovement(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                if (!scroller.isFinished()) {
                    scroller.abortAnimation();
                }
                int deltaY = (yLater - y);
                scrollBy(0, deltaY);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                velocityTracker.computeCurrentVelocity(1000);
                if (Math.abs(velocityTracker.getYVelocity()) > 8000) {
                    if (velocityTracker.getYVelocity() > 0)
                        scroller.startScroll(0, getScrollY(), 0, -300, 1000);
                    else
                        scroller.startScroll(0, getScrollY(), 0, 300, 1000);
                    invalidate();
                }
                velocityTracker.recycle();
                velocityTracker = null;
                break;
        }
        yLater = y;
        return true;
    }

    @Override
    public void computeScroll() {
        Log.e("computeScroll", "computeScroll: " + scroller.getCurrX() + "," + scroller.getCurrY());
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.getCurrX(), scroller.getCurrY());
            invalidate();
        }
    }
}

165:SparseArray和ArrayList,如果这两个类中都没有任何一个元素,都调用get(0)方法,SparseArray不会崩,但是ArrayList会崩(java.lang.IndexOutOfBoundsException: Index: 0, Size: 0)。

166:设置dialog透明的方式

<style name="dialog" parent="@android:style/Theme.Dialog">
        <item name="android:windowFrame">@null</item><!--边框-->
        <item name="android:windowIsFloating">true</item><!--是否浮现在activity之上-->
        <item name="android:windowIsTranslucent">false</item><!--半透明-->
        <item name="android:windowNoTitle">true</item><!--无标题-->
        <item name="android:windowBackground">@color/transparent</item><!--背景透明-->
        <item name="android:backgroundDimEnabled">false</item><!--模糊-->
    </style>

https://www.cnblogs.com/windlivefamily/articles/2133956.html

167:设置toolbar的menu的三个点为白色的方法

<style name="Theme.ToolBar.Menu" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
        <!-- 设置-弹窗的背景-颜色-->
        <item name="android:colorBackground">@color/common_bg</item>
        <!-- 字体的颜色-->
        <item name="android:textColor">@color/common_h1</item>
        <!-- 字体大小-->
        <item name="android:textSize">16sp</item>
        <!-- 用于替换菜单的三个小白点,换成自已的图片-->
        <item name="actionOverflowButtonStyle">@style/ActionButton.Overflow.Menu</item>
        <!--用于控制menu弹出的位置,位于toolbar的下面,而不是上面-->
        <item name="actionOverflowMenuStyle">@style/OverflowMenuStyle</item>
        <!-- 用于修改item默认的分割线-->
        <item name="android:dropDownListViewStyle">@style/dropDownStyle</item>
        <item name="dropDownListViewStyle">@style/dropDownStyle</item>
    </style>

    <style name="ActionButton.Overflow.Menu" parent="android:style/Widget.Holo.Light.ActionButton.Overflow">
        <item name="android:src">@drawable/abc_ic_menu_moreoverflow_mtrl_alpha</item>
    </style>

168:一个申请权限的框架

https://github.com/getActivity/XXPermissions

169:自定义layoutmanager,示例代码如下:

public class MyLayoutManager extends RecyclerView.LayoutManager {
    private int mDecoratedChildWidth;
    private int mDecoratedChildHeight;
    private int offset;
    private SparseArray<Rect> rectList;

    public MyLayoutManager(Context context) {
        rectList = new SparseArray<>();
    }

    @Override
    public RecyclerView.LayoutParams generateDefaultLayoutParams() {
        return new RecyclerView.LayoutParams(RecyclerView.LayoutParams.WRAP_CONTENT, RecyclerView.LayoutParams.WRAP_CONTENT);
    }

    @Override
    public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
        offset += dy;
        if (offset < 0) {
            offset = 0;
            return 0;
        }
        if (offset > (getItemCount() * mDecoratedChildHeight - getVerticalSpace())) {
            offset = getItemCount() * mDecoratedChildHeight - getVerticalSpace();
            return 0;//在scrollVerticallyBy方法中return 0会在recyclerview中出现椭圆动画
        }
        layoutChidren(recycler,state);//判断偏移量是否小于0或大于屏幕高度的代码必须放在重新绘制子view代码的前面,offsetChildrenVertica方法必须放在重新绘制子view代码的后面。
        offsetChildrenVertical(-offset);//将子view在垂直方向上进行滚动
        return dy;
    }

    @Override
    public boolean canScrollVertically() {
        return true;
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        super.onLayoutChildren(recycler, state);
        int left = 0, pianyi = 0;
        for (int i = 0; i < state.getItemCount(); i++) {
            View view = recycler.getViewForPosition(i);
            measureChildWithMargins(view, 0, 0);
            mDecoratedChildWidth = getDecoratedMeasuredWidth(view);
            mDecoratedChildHeight = getDecoratedMeasuredHeight(view);
            Rect rect = rectList.get(i);
            if (rect == null) {
                rect = new Rect();
            }
            rect.set(left, pianyi, left + mDecoratedChildWidth, pianyi + mDecoratedChildHeight);
            rectList.put(i, rect);
            pianyi += mDecoratedChildHeight;
        }
        layoutChidren(recycler,state);
    }

    private void layoutChidren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        detachAndScrapAttachedViews(recycler);
        Rect parent = new Rect(0, offset, getHorSpace(), offset + getVerticalSpace());
        for (int i = 0; i < state.getItemCount(); i++) {
            if (Rect.intersects(parent, rectList.get(i))) {
                View view = recycler.getViewForPosition(i);
                measureChildWithMargins(view, 0, 0);
                addView(view);
                layoutDecorated(view, 0, rectList.get(i).top, rectList.get(i).right, rectList.get(i).bottom);
            }
        }

        for (int i = 0; i < recycler.getScrapList().size(); i++) {
            RecyclerView.ViewHolder viewHolder=recycler.getScrapList().get(i);
            removeView(viewHolder.itemView);
            recycler.recycleView(viewHolder.itemView);
        }

       /* Rect childFrame = new Rect();
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            childFrame.left = getDecoratedLeft(child);
            childFrame.top = getDecoratedTop(child);
            childFrame.right = getDecoratedRight(child);
            childFrame.bottom = getDecoratedBottom(child);
            //如果Item没有在显示区域,就说明需要回收
            if (!Rect.intersects(parent, childFrame)) {
                //回收掉滑出屏幕的View
                removeAndRecycleView(child, recycler);

            }
        }*/
    }

    private int getVerticalSpace() {
        return getHeight() - getPaddingBottom() - getPaddingTop();
    }

    private int getHorSpace() {
        return getWidth() - getPaddingLeft() - getPaddingRight();
    }

    @Override
    public void onLayoutCompleted(RecyclerView.State state) {
        super.onLayoutCompleted(state);
        LogUtils.e("MyLayoutManager", "布局完成");
    }
}

https://blog.csdn.net/u011387817/article/details/81875021

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342