安卓自定义view中invalidate后并没有调用ondraw(),是怎么回事啊?

安卓自定义view中invalidate后并没有调用ondraw(),是怎么回事啊?

1个回答

你把系统那个方法给重写了吧,那个super() 不能删除的,这个会调用系统的方法。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
关于android自定义View的requestLauout和invalidate我一直有个疑问
查询百度,会有下面的解释 requestLayout:会调用onMeasure onLayout invalidate:会调用onDraw 问题1:为什么我自定义的View,我在调用requestLayout时依然会调用onDraw这个方法 问题2:为什么我调用invalidate(rect)进行局部刷新时会重新走一遍onDraw的所有方法,而不是只走对应的局部方法,这样的话和invalidate就没有区别了啊? 问题3:在自定义ViewGroup时,在init时new出一个View并add上去,调用ViewGroup的requestLayout方法后,发现没有调用这个View的onMeasure方法,或者调用ViewGroup的invalidate后,发现没有调用子View的onDraw方法。 这些问题都是为什么?请相关大牛帮忙细心解释。
android 自定义view调用invalidate有时候保留上次绘制的线
如题,本人自定义一个折线图,应为数据接口合不上就弄了一个适配器模式匹配数据,但是多次跟新数据重新设置适配器时候,有时发现折线图会出现上一次数据绘制的一根线,代码如下: @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); getPaint().reset(); /** * 外框线 */ // 设置颜色 getPaint().setColor(substrateColor); // 设置宽度 getPaint().setStrokeWidth(2); // 线的坐标点 (四个为一条线) float[] pts = {LEFTUPX, LEFTUPY - 20, LEFTUPX, LEFTDOWNY, LEFTUPX, LEFTDOWNY, RIGHTDOWNX + 20, LEFTDOWNY}; // 画线 canvas.drawLines(pts, getPaint()); /** * 箭头 */ // 通过路径画三角形 Path path = new Path(); getPaint().setStyle(Paint.Style.FILL);// 设置为空心 path.moveTo(LEFTUPX - 5, LEFTUPY - 20);// 此点为多边形的起点 path.lineTo(LEFTUPX + 5, LEFTUPY - 20); path.lineTo(LEFTUPX, LEFTUPY - 35); path.close(); // 使这些点构成封闭的多边形 canvas.drawPath(path, getPaint()); // 第二个箭头 path.moveTo(RIGHTDOWNX + 20, LEFTDOWNY - 5);// 此点为多边形的起点 path.lineTo(RIGHTDOWNX + 20, LEFTDOWNY + 5); path.lineTo(RIGHTDOWNX + 35, LEFTDOWNY); canvas.drawPath(path, getPaint()); /** * 中间虚线 */ float[] pts2 = new float[(updownlines + leftrightlines) * 4]; // 计算位置y轴标题 if (updownlines != 0) { for (int i = 0; i < updownlines; i++) { float x1 = LEFTUPX; float y1 = LEFTDOWNY - (i + 1) * UPDOWNSPACE; float x2 = RIGHTDOWNX; float y2 = LEFTDOWNY - (i + 1) * UPDOWNSPACE; pts2[i * 4 + 0] = x1; pts2[i * 4 + 1] = y1; pts2[i * 4 + 2] = x2; pts2[i * 4 + 3] = y2; getPaint().setColor(Color.BLACK); getPaint().setTextSize(25); if (showRule != null) { if (showRule.showVerticalTitle(i)) canvas.drawText(String.valueOf(verticalTitle[i]), x1 + 5, y1 + 10, getPaint(titleColor)); } else { canvas.drawText(String.valueOf(i), x1 + 5, y1 + 10, getPaint(titleColor)); } } } // 计算位置x轴上标题 if (leftrightlines != 0) { for (int i = 0; i < leftrightlines; i++) { float x1 = LEFTUPX + (i + 1) * LEFTRIGHTSPACE; float y1 = LEFTUPY; float x2 = LEFTUPX + (i + 1) * LEFTRIGHTSPACE; float y2 = LEFTDOWNY; pts2[(i + updownlines) * 4 + 0] = x1; pts2[(i + updownlines) * 4 + 1] = y1; pts2[(i + updownlines) * 4 + 2] = x2; pts2[(i + updownlines) * 4 + 3] = y2; if (showRule != null) { if (showRule.showLandsTitle(i)) { Paint pen = getPaint(); if (showRule.markLandsTitle(String.valueOf(lanspaceTitle[i]))) { pen.setColor(markTitleColor); Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD); pen.setTypeface(font); } else { pen.setColor(titleColor); Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL); pen.setTypeface(font); } canvas.drawText(String.valueOf(lanspaceTitle[i]), x2 - 10, y2 + 30, pen); } } else { canvas.drawText(String.valueOf(i), x2 - 10, y2 + 30, getPaint(titleColor)); } } if (showRule != null && !TextUtils.isEmpty(showRule.landsUnit())) { float[] widths = new float[1]; float width = 0; for (int j = 0; j < (String.valueOf(lanspaceTitle[lanspaceTitle.length - 1])).length(); j++) { getPaint().getTextWidths(String.valueOf((String.valueOf(lanspaceTitle[lanspaceTitle.length - 1]).charAt(j))), widths); width += widths[0]; } canvas.drawText(showRule.landsUnit(), LEFTUPX + (leftrightlines) * LEFTRIGHTSPACE + width, LEFTDOWNY + 30, getPaint(titleColor)); } } getPaint().setColor(imaginaryLineColor); getPaint().setStrokeWidth(1); if (showRule != null && showRule.showImaginaryLine()) canvas.drawLines(pts2, getPaint()); getPaint().setStrokeWidth(2); if (showRule != null) { if (intervalTime == 0) { number = 50; count = dataSize - 1; //一定要先画矮的那根线,否则会被遮盖 if (/*listY2.size() > 0*/list.size() > 0) canvasDataLines(canvas, 1, firstLineColor, firstBelowColor); if (list.size() > 0) canvasDataLines(canvas, 0, secondLineColor, secondBelowColor); isFinish = true; } else { if (list.size() > 0) canvasDataLines(canvas, 1, firstLineColor, firstBelowColor); if (list.size() > 0) canvasDataLines(canvas, 0, secondLineColor, secondBelowColor); handler.sendEmptyMessage(1); } } if (clickPoint != null) { Log.e("Click", "postInvalidate--->>>onDraw"); //点击后的浮现效果出现 selectedView.setPointf(clickPoint.getLine() == PointBean.THEFIRSTLINE ? clickPoint.getUppointF() : clickPoint.getDownPoint()) .setAlterBgColor(clickPoint.getLine() == PointBean.THEFIRSTLINE ? clickSecondLineBgColor : clickFirstLineBgColor) .setFontColor(clickPoint.getLine() == PointBean.THEFIRSTLINE ? clickFirstLineFontColor : clickSecondLineFontColor) .setCircleColor(clickPoint.getLine() == PointBean.THEFIRSTLINE ? clickSecondLineCircleColor : clickFirstLineCircleColor) .setTextValue(clickPoint.getLine() == PointBean.THEFIRSTLINE ? clickPoint.getText() : clickPoint.getText2()) .setMargin(selectedView.getCrossBorder()?-50:30) .draw(canvas); //如果需要这个浮现效果自动消失就用一个handler将clickPoint制空并且重新绘制就好了 } } /** * 画折线 * * @param canvas * @param listY * @param color * @param endColor */ private synchronized void canvasDataLines(Canvas canvas, int flag, int color, int endColor) { // 线的路径 Path path2 = new Path(); // 共几个转折点 for (int i = 0; i < count; i++) { if (i == 0) { path2.moveTo(list.get(i).getX(), flag==0?list.get(i).getY1():list.get(i).getY2()); } else { path2.lineTo(list.get(i).getX(), flag==0?list.get(i).getY1():list.get(i).getY2()); } } // 上一个点 减去 下一个点的位置 计算中间点位置 path2.lineTo(list.get(count - 1).getX() + (list.get(count).getX() - list.get(count - 1).getX()) / 50 * number, flag==0?list.get(count - 1).getY1():list.get(count - 1).getY2() + (flag==0?list.get(count).getY1():list.get(count).getY2() - flag==0?list.get(count - 1).getY1():list.get(count - 1).getY2()) / 50 * number); getPaint().setColor(color); getPaint().setStrokeWidth(2); getPaint().setStyle(Paint.Style.STROKE);// 设置为空心 canvas.drawPath(path2, getPaint()); path2.lineTo(list.get(count - 1).getX() + (list.get(count).getX() - list.get(count - 1).getX()) / 50 * number, LEFTDOWNY); path2.lineTo(list.get(0).getX(), LEFTDOWNY); path2.lineTo(list.get(0).getX(), flag==0?list.get(0).getY1():list.get(0).getY2()); getPaint().setStyle(Paint.Style.FILL);// 设置为空心 canvas.drawPath(path2, getShadeColorPaint(endColor,color)); getPaint().reset(); }
子view里的onDraw不执行,求解。。。。。
一个子view外面套了两层ViewGroup,初始时这个子View的状态为gone,当进行操作时把子view的状态更改为visible,然后调用invalidate();但这样子view的ondraw根本触发不了。。。。这是什么原因啊?? ps:1、如果就套了一层viewgroup,gone->visible后,子view的ondraw还是能调用到的 2、如果初始状态为invisible,操作时改为visible,子view的ondraw也是能调用到的 附个demo地址[CSDN移动问答][1] [1]: http://www.eoeandroid.com/thread-298900-1-1.html
android开发view重画的时候能否不清空以前的内容呢?
我想在android上做个小游戏,其中有一个环节是在view上重载onDraw函数来画图,然后在需要更新图像的时候调用invalidate来实现重画.现在的问题是每次调用invalidate的时候,原来画的图都被清空了,我必须把原来画好的图重新画一次,很影响效率.所以我想问一下,[b]能否实现在重画的时候不清空上次onDraw的时候已经画好的图像啊?[/b] :wink: [b]问题补充:[/b] 如果不调用invalidate,怎么触发重画呢? 我也尝试着在view类里面加一个成员变量canvas,在重载onDraw的时候将传进来的canvas记录下来,在需要调用invalidate的时候调用onDraw来代替,可是似乎不起作用(进入了onDraw函数,但是画图的代码都没有被调用...或者是记录下来的canvas有问题??).
如何在Android4.0.4锁屏界面的电话图标右上角显示未接电话个数?
目前,未接电话个数也要获取到。存在的问题就是如何在电话图标右上角显示未接电话个数? 电话图标是控件MultiWaveView上的图标,该类是系统已经定义好的。我想通过直接集成View来自定义自己的View,然后在OnDraw函数通过Canvas和paint,指定坐标来画。但始终是没有显示出来。自定义view的OnDraw函数也有跑到。请指教要实现这效果,该怎样是画未接个数呢?效果图:![enter image description here][1] 我是在自定义的handler中调用构造函数。每10s就会handler处理。 private final Handler mUpdateMissCallNum = new Handler() { @Override public void handleMessage(Message msg) { Log.i(TAG, "mUpdateMissCallNum"); switch (msg.what) { case UPDATESTART: Log.i(TAG, "UPDATESTART"); sNewMissedCallCount = getMissedCallCount(mContext); if (sNewMissedCallCount != sTempMissedCallCount) { Log.i(TAG, "sNewMissedCallCount != sTempMissedCallCount"); new Thread(new Runnable() { public void run() { Log.i(TAG, "sNewMissedCallCount is:"+sNewMissedCallCount); Log.i(TAG, "sTempMissedCallCount is:"+sTempMissedCallCount); sTempMissedCallCount = sNewMissedCallCount; mMissedCallView=new MissedCallView(mContext,sTempMissedCallCount); Log.i(TAG, "sTempMissedCallCount is:"+sTempMissedCallCount); } } ).start(); } break; default: break; } } } mMissedCallView=new MissedCallView(mContext,sTempMissedCallCount);这就是我调用自定义view的地方。通过直接用坐标和canvas,paint画,不要再在xml文件里去写吧。 锁屏用到的xml文件:Keyguardscreentabunlock.xml (framework\base\core\res\res\layout)该文件中用系统自定义的波纹锁屏 <com.android.internal.widget.multiwaveview.MultiWaveView android:id="@+id/unlockwidget" android:orientation="horizontal" android:layoutwidth="matchparent" android:layoutheight="matchparent" android:layout_alignParentBottom="true" android:targetDrawables="@array/lockscreen_targets_with_camera" android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera" android:directionDescriptions="@array/lockscreen_direction_descriptions" android:handleDrawable="@drawable/ic_lockscreen_handle" android:waveDrawable="@drawable/ic_lockscreen_outerring" android:outerRadius="@dimen/multiwaveview_target_placement_radius" android:snapMargin="@dimen/multiwaveview_snap_margin" android:hitRadius="@dimen/multiwaveview_hit_radius" android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right" android:horizontalOffset="0dip" android:verticalOffset="60dip" android:feedbackCount="3" android:vibrationDuration="20" /> 效果图:![enter image description here][2] 我们只是把相机改成了拨号,就是在这拨号图标上打算画上未接电话数。请指教,谢谢! 这个类存放位置:framework\base\core\java\com\android\internal\widget\multiwaveview\MissedCallView.java public class MissedCallView extends View { private static final String TAG = "MissedCallViews"; public static final int UPDATESTART = 10; private static final int DELAYTIME = 10000; private int sTempMissedCallCount=-1; Context mContext; Canvas mCanvas; public MissedCallView(Context context) { super(context); Log.i(TAG, "MissedCallView1"); mCanvas=new Canvas(); } public MissedCallView(Context context, AttributeSet attrs) { super(context, attrs); Log.i(TAG, "MissedCallView2"); mCanvas=new Canvas(); } public MissedCallView(Context context,int missedCallNum) { super(context); sTempMissedCallCount=missedCallNum; Log.i(TAG, "MissedCallView3"); mCanvas=new Canvas(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(sTempMissedCallCount>0) { Paint paint=new Paint(Paint.ANTIALIASFLAG); paint.setColor(Color.RED); Log.i(TAG,"Integer.toString(sTempMissedCallCount)is:"+Integer.toString(sTempMissedCallCount)); canvas.drawText(Integer.toString(sTempMissedCallCount),40,310,paint);//50 invalidate(); Log.i(TAG, "invalidate"); } } } 这是自定义view。只跑了 这个构造函数MissedCallView(Context context,int missedCallNum)。是在我定义的public class MissCallObserver extends ContentObserver监听未接电话个数类中调用的。为什么没有跑onDraw函数?请指教。未接电话个数获取是正确的。关键是显示了。 [1]: http://img.my.csdn.net/uploads/201211/30/1354253964_5230.jpg [2]: http://img.my.csdn.net/uploads/201212/04/1354596263_8902.png
按下按钮后擦除器没有调用
main class: public class Main extends Activity { Button edit,save,eraser,clear; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); edit = (Button) findViewById(R.id.edit); save = (Button) findViewById(R.id.save); clear = (Button) findViewById(R.id.clear); eraser = (Button) findViewById(R.id.eraser); eraser.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { GameBoard aa = new GameBoard(Main.this); aa.eraser(); aa.invalidate(); } }); } } 视图类: public class GameBoard extends View{ public void init() { mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setDither(true); // mPaint.setColor(Color.BLACK); mPaint.setColor(0xFFFF0000); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(12); } public Paint mPaint; public GameBoard(Context context) { super(context); init(); } private Bitmap mBitmap; private Canvas mCanvas; private Path mPath; private Paint mBitmapPaint; public GameBoard(Context context, AttributeSet aSet) { super(context, aSet); init(); mBitmap = Bitmap.createBitmap(800, 1024, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); mPath = new Path(); mBitmapPaint = new Paint(Paint.DITHER_FLAG); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); } @Override public void onDraw(Canvas canvas) { // initialize // canvas.drawColor(Color.WHITE); canvas.drawColor(0xFFAAAAAA); canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); canvas.drawPath(mPath, mPaint); } private float mX, mY; private static final float TOUCH_TOLERANCE = 4; private void touch_start(float x, float y) { mPath.reset(); mPath.moveTo(x, y); mX = x; mY = y; } private void touch_move(float x, float y) { float dx = Math.abs(x - mX); float dy = Math.abs(y - mY); if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2); mX = x; mY = y; } } private void touch_up() { mPath.lineTo(mX, mY); // commit the path to our offscreen mCanvas.drawPath(mPath, mPaint); // kill this so we don't double draw mPath.reset(); } @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: touch_start(x, y); invalidate(); break; case MotionEvent.ACTION_MOVE: touch_move(x, y); invalidate(); break; case MotionEvent.ACTION_UP: touch_up(); invalidate(); break; } return true; } public void eraser() { // TODO Auto-generated method stub Toast.makeText(getContext(), "eraser", Toast.LENGTH_LONG).show(); mPaint.setXfermode(null); mPaint.setAlpha(0xFF); mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); invalidate(); } } 布局文件: <com.authorwjf.GameBoard android:id="@+id/the_canvas" android:layout_width="fill_parent" android:layout_height="fill_parent" /> 但是在点击按钮的时候,没有将`mPaint`转换到`eraser`
请教关于Android中Looper的一个问题
在循环中handler.sendMessage(msg)后,利用Looper.loop()来调用handler.handleMessage(msg),如何让loop()退出执行下个迭代? [code="java"] public class MainActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MyView view = new MyView(this, null); setContentView(view); } // 自定义视图类 class MyView extends View implements Runnable{ // 图形当前坐标 private int x=20, y=20; public MyView(Context context, AttributeSet attrs) { super(context, attrs); // 获得焦点 setFocusable(true); // 启动线程 new Thread(this).start(); } @Override public void run() { Looper.prepare(); Handler refreshHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if(msg.what==0x101111){ MyView.this.update(); MyView.this.invalidate(); } } }; while(!Thread.currentThread().isInterrupted()){ // 通过发送消息更新界面 Message msg = refreshHandler.obtainMessage(); msg.what = 0x101111; refreshHandler.sendMessage(msg); Looper.loop(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 实例化画笔 Paint paint = new Paint(); // 设置画笔颜色 paint.setColor(Color.GREEN); // 画圆 canvas.drawCircle(x, y, 10, paint); } // 更新坐标 private void update(){ int h = 500; y += 5; if(y>=h) y = 20; } } } [/code]
请问android在webview上用canvas绘制四圆点,拖动后原来的点却无法删除呢?
需求是: 点击一个button,点击一次在webview上绘制两个圆点,点击第二次再绘制两个圆点,监听这四个圆点的触摸移动,将原来绘制的点隐藏会删除,请看代码: button.setonclicklisterner(new View.onclicklistener{ measure_count = ++measure_count; int result = measure_count % 3; LogUtil.i("TAG=" + getClass().getSimpleName(), "result=" + result); switch (result) { case 0: break; case 1: if (DotCanvasView.mCircleInfos != null) { DotCanvasView.mCircleInfos.clear(); } dotCanvasMethod(dotOneX, dotOneY, 0); dotCanvasMethod(dotTwoX, dotTwoY, 1); break; case 2: if (DotCanvasView.mCircleInfos != null) { DotCanvasView.mCircleInfos.clear(); } dotCanvasMethod(dotOneX, dotOneY, 0); dotCanvasMethod(dotTwoX, dotTwoY, 1); dotCanvasMethod(dotThreeX, dotThreeY,2); dotCanvasMethod(dotFourX, dotFourY, 3); break; default: break; } } ``` private void dotCanvasMethod(float dotx, float doty, int tag) { view = new DotCanvasView(this); dotInfo = new DotCanvasView.CircleInfo(); dotInfo.setX(dotx); dotInfo.setY(doty); dotInfo.setTag(tag); DotCanvasView.mCircleInfos.add(dotInfo); view.setMinimumHeight(40); view.setMinimumWidth(40); //通知view组件重绘 view.invalidate(); frame_layout.addView(view); } ``` //圆点绘制类 public class DotCanvasView extends View { public DotCanvasView(Context context) { super(context); } // 保存绘制历史 public static List<CircleInfo> mCircleInfos = new ArrayList<CircleInfo>(); // 保存实心圆相关信息的类 public static class CircleInfo { private float x; // 圆心横坐标 private float y; // 圆心纵坐标 private int tag; //实心圆的标示 public float getX() { return x; } public void setX(float x) { this.x = x; } public float getY() { return y; } public void setY(float y) { this.y = y; } public int getTag() { return tag; } public void setTag(int tag) { this.tag = tag; } } // 当画布重绘时调用该方法,Canvas表示画布对象,可以在该对象上绘制基本的图形 @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint(); paint.setAntiAlias(true); // 设置画笔颜色 canvas.save(); paint.setColor(Color.GREEN); // 根据保存的绘制历史重绘所有的实心圆 for (CircleInfo circleInfo : mCircleInfos) { // 绘制实心圆 canvas.drawCircle(circleInfo.getX(), circleInfo.getY(), 20, paint); canvas.save(); } LogUtil.i("TAG=" + getClass().getSimpleName(), "saveCount=" + canvas.getSaveCount()); if (canvas.getSaveCount() >1) { canvas.restoreToCount(1); } } @Override public boolean onTouchEvent(MotionEvent event) { float currentX = event.getX(); float currentY = event.getY(); LogUtil.i("TAG=" + getClass().getSimpleName(), "currentX=" + currentX + "currentY=" + currentY); if (mCircleInfos != null) { for (CircleInfo circledot : mCircleInfos) { if (currentX < (circledot.getX() + 20) && currentX > (circledot.getX() - 20) && currentY < (circledot.getY() + 20) && currentY > (circledot.getY() - 20)) { LogUtil.i("TAG=" + getClass().getSimpleName(), "111dot=" + circledot.getTag() + " dotX=" + circledot.getX() + " doty=" + circledot.getY()); CircleInfo circleInfo = new CircleInfo(); circleInfo.setTag(circledot.getTag()); LogUtil.i("TAG=" + getClass().getSimpleName(), "222tag=" + circledot.getTag()); circleInfo.setX(currentX); circleInfo.setY(currentY); mCircleInfos.set(circledot.getTag(), circleInfo); mCircleInfos.remove(circledot); invalidate(); } LogUtil.i("TAG=" + getClass().getSimpleName(), "333dot=" + circledot.getTag() + " x=" + circledot.getX() + " y=" + circledot.getY()); } } return true; } } xml布局文件: <?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:orientation="vertical"> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="match_parent"/> <FrameLayout android:id="@+id/frame_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:id="@+id/regional_webView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_horizontal" android:scrollbars="none" /> </FrameLayout> </LinearLayout>
画圆弧的时候sweepAngle参数等于135的时候圆弧显示的怪异
> public class CircleProgressBar extends View{ private int hour; private int maxProgress = 24; private int progress; int progress1; private int progressStrokeWidth = 32; RectF oval; Paint paint; Paint paint1; public CircleProgressBar(Context context, AttributeSet attrs) { super(context, attrs); oval = new RectF(); paint = new Paint(); paint1 = new Paint(); } @Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); Calendar c=Calendar.getInstance(); hour = c.get(Calendar.HOUR_OF_DAY); progress = hour; int width = this.getWidth(); int height = this.getHeight(); if(width != height){ int min = Math.min(width, height); width = min; height = min; } paint.setAntiAlias(true); paint.setColor(Color.LTGRAY); canvas.drawColor(Color.BLACK); paint.setStrokeWidth(15); paint.setStyle(Style.STROKE); oval.left = progressStrokeWidth / 2; // 左上角x oval.top = progressStrokeWidth / 2; // 左上角y oval.right = width - progressStrokeWidth / 2; // 左下角x oval.bottom = height - progressStrokeWidth / 2; // 右下角y canvas.drawArc(oval, -90, 360, false, paint); paint.setColor(Color.rgb(0x57, 0x87, 0xb6)); // paint.setStrokeCap(Paint.Cap.ROUND); paint.setColor(Color.CYAN); canvas.drawArc(oval, -90, 135, false, paint); paint.setStrokeJoin(Paint.Join.ROUND); paint.setStrokeWidth(15); String text = (long)(((float) progress / maxProgress) * 100) + "%"; int textHeight = height / 4; paint.setTextSize(textHeight); int textWidth = (int) paint.measureText(text, 0, text.length()); paint.setStyle(Style.FILL); canvas.drawText(text, width / 2 - textWidth / 2, height / 2 +textHeight/2, paint); } public int getMaxProgress() { return maxProgress; } public void setMaxProgress(int maxProgress) { this.maxProgress = maxProgress; } public void setProgress(int progress) { this.progress = progress; this.invalidate(); } /** * 非UI线程调用 */ public void setProgressNotInUiThread(int progress) { this.progress = progress; this.postInvalidate(); } } 显示的结果是![](device-2014-12-24-113514.png)
Java学习的正确打开方式
在博主认为,对于入门级学习java的最佳学习方法莫过于视频+博客+书籍+总结,前三者博主将淋漓尽致地挥毫于这篇博客文章中,至于总结在于个人,实际上越到后面你会发现学习的最好方式就是阅读参考官方文档其次就是国内的书籍,博客次之,这又是一个层次了,这里暂时不提后面再谈。博主将为各位入门java保驾护航,各位只管冲鸭!!!上天是公平的,只要不辜负时间,时间自然不会辜负你。 何谓学习?博主所理解的学习,它是一个过程,是一个不断累积、不断沉淀、不断总结、善于传达自己的个人见解以及乐于分享的过程。
程序员必须掌握的核心算法有哪些?
由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散的,并没有一本把他们全部覆盖的书籍。下面是我觉得值得学习的一些算法以及数据结构,当然,我也会整理一些看过...
大学四年自学走来,这些私藏的实用工具/学习网站我贡献出来了
大学四年,看课本是不可能一直看课本的了,对于学习,特别是自学,善于搜索网上的一些资源来辅助,还是非常有必要的,下面我就把这几年私藏的各种资源,网站贡献出来给你们。主要有:电子书搜索、实用工具、在线视频学习网站、非视频学习网站、软件下载、面试/求职必备网站。 注意:文中提到的所有资源,文末我都给你整理好了,你们只管拿去,如果觉得不错,转发、分享就是最大的支持了。 一、电子书搜索 对于大部分程序员...
linux系列之常用运维命令整理笔录
本博客记录工作中需要的linux运维命令,大学时候开始接触linux,会一些基本操作,可是都没有整理起来,加上是做开发,不做运维,有些命令忘记了,所以现在整理成博客,当然vi,文件操作等就不介绍了,慢慢积累一些其它拓展的命令,博客不定时更新 free -m 其中:m表示兆,也可以用g,注意都要小写 Men:表示物理内存统计 total:表示物理内存总数(total=used+free) use...
比特币原理详解
一、什么是比特币 比特币是一种电子货币,是一种基于密码学的货币,在2008年11月1日由中本聪发表比特币白皮书,文中提出了一种去中心化的电子记账系统,我们平时的电子现金是银行来记账,因为银行的背后是国家信用。去中心化电子记账系统是参与者共同记账。比特币可以防止主权危机、信用风险。其好处不多做赘述,这一层面介绍的文章很多,本文主要从更深层的技术原理角度进行介绍。 二、问题引入 假设现有4个人...
程序员接私活怎样防止做完了不给钱?
首先跟大家说明一点,我们做 IT 类的外包开发,是非标品开发,所以很有可能在开发过程中会有这样那样的需求修改,而这种需求修改很容易造成扯皮,进而影响到费用支付,甚至出现做完了项目收不到钱的情况。 那么,怎么保证自己的薪酬安全呢? 我们在开工前,一定要做好一些证据方面的准备(也就是“讨薪”的理论依据),这其中最重要的就是需求文档和验收标准。一定要让需求方提供这两个文档资料作为开发的基础。之后开发...
网页实现一个简单的音乐播放器(大佬别看。(⊙﹏⊙))
今天闲着无事,就想写点东西。然后听了下歌,就打算写个播放器。 于是乎用h5 audio的加上js简单的播放器完工了。 演示地点演示 html代码如下` music 这个年纪 七月的风 音乐 ` 然后就是css`*{ margin: 0; padding: 0; text-decoration: none; list-...
Python十大装B语法
Python 是一种代表简单思想的语言,其语法相对简单,很容易上手。不过,如果就此小视 Python 语法的精妙和深邃,那就大错特错了。本文精心筛选了最能展现 Python 语法之精妙的十个知识点,并附上详细的实例代码。如能在实战中融会贯通、灵活使用,必将使代码更为精炼、高效,同时也会极大提升代码B格,使之看上去更老练,读起来更优雅。
数据库优化 - SQL优化
以实际SQL入手,带你一步一步走上SQL优化之路!
通俗易懂地给女朋友讲:线程池的内部原理
餐盘在灯光的照耀下格外晶莹洁白,女朋友拿起红酒杯轻轻地抿了一小口,对我说:“经常听你说线程池,到底线程池到底是个什么原理?”
经典算法(5)杨辉三角
杨辉三角 是经典算法,这篇博客对它的算法思想进行了讲解,并有完整的代码实现。
使用 Docker 部署 Spring Boot 项目
Docker 技术发展为微服务落地提供了更加便利的环境,使用 Docker 部署 Spring Boot 其实非常简单,这篇文章我们就来简单学习下。首先构建一个简单的 S...
英特尔不为人知的 B 面
从 PC 时代至今,众人只知在 CPU、GPU、XPU、制程、工艺等战场中,英特尔在与同行硬件芯片制造商们的竞争中杀出重围,且在不断的成长进化中,成为全球知名的半导体公司。殊不知,在「刚硬」的背后,英特尔「柔性」的软件早已经做到了全方位的支持与支撑,并持续发挥独特的生态价值,推动产业合作共赢。 而对于这一不知人知的 B 面,很多人将其称之为英特尔隐形的翅膀,虽低调,但是影响力却不容小觑。 那么,在...
面试官:你连RESTful都不知道我怎么敢要你?
干货,2019 RESTful最贱实践
刷了几千道算法题,这些我私藏的刷题网站都在这里了!
遥想当年,机缘巧合入了 ACM 的坑,周边巨擘林立,从此过上了"天天被虐似死狗"的生活… 然而我是谁,我可是死狗中的战斗鸡,智力不够那刷题来凑,开始了夜以继日哼哧哼哧刷题的日子,从此"读题与提交齐飞, AC 与 WA 一色 ",我惊喜的发现被题虐既刺激又有快感,那一刻我泪流满面。这么好的事儿作为一个正直的人绝不能自己独享,经过激烈的颅内斗争,我决定把我私藏的十几个 T 的,阿不,十几个刷题网...
白话阿里巴巴Java开发手册高级篇
不久前,阿里巴巴发布了《阿里巴巴Java开发手册》,总结了阿里巴巴内部实际项目开发过程中开发人员应该遵守的研发流程规范,这些流程规范在一定程度上能够保证最终的项目交付质量,通过在时间中总结模式,并推广给广大开发人员,来避免研发人员在实践中容易犯的错误,确保最终在大规模协作的项目中达成既定目标。 无独有偶,笔者去年在公司里负责升级和制定研发流程、设计模板、设计标准、代码标准等规范,并在实际工作中进行...
SQL-小白最佳入门sql查询一
不要偷偷的查询我的个人资料,即使你再喜欢我,也不要这样,真的不好;
redis分布式锁,面试官请随便问,我都会
文章有点长并且绕,先来个图片缓冲下! 前言 现在的业务场景越来越复杂,使用的架构也就越来越复杂,分布式、高并发已经是业务要求的常态。像腾讯系的不少服务,还有CDN优化、异地多备份等处理。 说到分布式,就必然涉及到分布式锁的概念,如何保证不同机器不同线程的分布式锁同步呢? 实现要点 互斥性,同一时刻,智能有一个客户端持有锁。 防止死锁发生,如果持有锁的客户端崩溃没有主动释放锁,也要保证锁可以正常释...
项目中的if else太多了,该怎么重构?
介绍 最近跟着公司的大佬开发了一款IM系统,类似QQ和微信哈,就是聊天软件。我们有一部分业务逻辑是这样的 if (msgType = "文本") { // dosomething } else if(msgType = "图片") { // doshomething } else if(msgType = "视频") { // doshomething } else { // doshom...
Nginx 原理和架构
Nginx 是一个免费的,开源的,高性能的 HTTP 服务器和反向代理,以及 IMAP / POP3 代理服务器。Nginx 以其高性能,稳定性,丰富的功能,简单的配置和低资源消耗而闻名。 Nginx 的整体架构 Nginx 里有一个 master 进程和多个 worker 进程。master 进程并不处理网络请求,主要负责调度工作进程:加载配置、启动工作进程及非停升级。worker 进程负责处...
“狗屁不通文章生成器”登顶GitHub热榜,分分钟写出万字形式主义大作
一、垃圾文字生成器介绍 最近在浏览GitHub的时候,发现了这样一个骨骼清奇的雷人项目,而且热度还特别高。 项目中文名:狗屁不通文章生成器 项目英文名:BullshitGenerator 根据作者的介绍,他是偶尔需要一些中文文字用于GUI开发时测试文本渲染,因此开发了这个废话生成器。但由于生成的废话实在是太过富于哲理,所以最近已经被小伙伴们给玩坏了。 他的文风可能是这样的: 你发现,...
程序员:我终于知道post和get的区别
是一个老生常谈的话题,然而随着不断的学习,对于以前的认识有很多误区,所以还是需要不断地总结的,学而时习之,不亦说乎
《程序人生》系列-这个程序员只用了20行代码就拿了冠军
你知道的越多,你不知道的越多 点赞再看,养成习惯GitHub上已经开源https://github.com/JavaFamily,有一线大厂面试点脑图,欢迎Star和完善 前言 这一期不算《吊打面试官》系列的,所有没前言我直接开始。 絮叨 本来应该是没有这期的,看过我上期的小伙伴应该是知道的嘛,双十一比较忙嘛,要值班又要去帮忙拍摄年会的视频素材,还得搞个程序员一天的Vlog,还要写BU...
加快推动区块链技术和产业创新发展,2019可信区块链峰会在京召开
11月8日,由中国信息通信研究院、中国通信标准化协会、中国互联网协会、可信区块链推进计划联合主办,科技行者协办的2019可信区块链峰会将在北京悠唐皇冠假日酒店开幕。   区块链技术被认为是继蒸汽机、电力、互联网之后,下一代颠覆性的核心技术。如果说蒸汽机释放了人类的生产力,电力解决了人类基本的生活需求,互联网彻底改变了信息传递的方式,区块链作为构造信任的技术有重要的价值。   1...
Java世界最常用的工具类库
Apache Commons Apache Commons有很多子项目 Google Guava 参考博客
程序员把地府后台管理系统做出来了,还有3.0版本!12月7号最新消息:已在开发中有github地址
第一幕:缘起 听说阎王爷要做个生死簿后台管理系统,我们派去了一个程序员…… 996程序员做的梦: 第一场:团队招募 为了应对地府管理危机,阎王打算找“人”开发一套地府后台管理系统,于是就在地府总经办群中发了项目需求。 话说还是中国电信的信号好,地府都是满格,哈哈!!! 经常会有外行朋友问:看某网站做的不错,功能也简单,你帮忙做一下? 而这次,面对这样的需求,这个程序员...
网易云6亿用户音乐推荐算法
网易云音乐是音乐爱好者的集聚地,云音乐推荐系统致力于通过 AI 算法的落地,实现用户千人千面的个性化推荐,为用户带来不一样的听歌体验。 本次分享重点介绍 AI 算法在音乐推荐中的应用实践,以及在算法落地过程中遇到的挑战和解决方案。 将从如下两个部分展开: AI算法在音乐推荐中的应用 音乐场景下的 AI 思考 从 2013 年 4 月正式上线至今,网易云音乐平台持续提供着:乐屏社区、UGC...
【技巧总结】位运算装逼指南
位算法的效率有多快我就不说,不信你可以去用 10 亿个数据模拟一下,今天给大家讲一讲位运算的一些经典例子。不过,最重要的不是看懂了这些例子就好,而是要在以后多去运用位运算这些技巧,当然,采用位运算,也是可以装逼的,不信,你往下看。我会从最简单的讲起,一道比一道难度递增,不过居然是讲技巧,那么也不会太难,相信你分分钟看懂。 判断奇偶数 判断一个数是基于还是偶数,相信很多人都做过,一般的做法的代码如下...
为什么要学数据结构?
一、前言 在可视化化程序设计的今天,借助于集成开发环境可以很快地生成程序,程序设计不再是计算机专业人员的专利。很多人认为,只要掌握几种开发工具就可以成为编程高手,其实,这是一种误解。要想成为一个专业的开发人员,至少需要以下三个条件: 1) 能够熟练地选择和设计各种数据结构和算法 2) 至少要能够熟练地掌握一门程序设计语言 3) 熟知所涉及的相关应用领域的知识 其中,后两个条件比较容易实现,而第一个...
Android 9.0 init 启动流程
阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android本篇文章主要介绍Android开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:一、启动流程概述一、 启动流程概述Android启动流程跟Linux启动类似,大致分为如下五个阶段。1.开机上电,加载固化的ROM。2.加载BootLoader,拉起Android OS。3.加载Uboot,初始外设,引导Kernel启动等。...
8年经验面试官详解 Java 面试秘诀
作者 |胡书敏 责编 | 刘静 出品 | CSDN(ID:CSDNnews) 本人目前在一家知名外企担任架构师,而且最近八年来,在多家外企和互联网公司担任Java技术面试官,前后累计面试了有两三百位候选人。在本文里,就将结合本人的面试经验,针对Java初学者、Java初级开发和Java开发,给出若干准备简历和准备面试的建议。 Java程序员准备和投递简历的实...
面试官如何考察你的思维方式?
1.两种思维方式在求职面试中,经常会考察这种问题:北京有多少量特斯拉汽车?某胡同口的煎饼摊一年能卖出多少个煎饼?深圳有多少个产品经理?一辆公交车里能装下多少个乒乓球?一个正常成年人有多少根头发?这类估算问题,被称为费米问题,是以科学家费米命名的。为什么面试会问这种问题呢?这类问题能把两类人清楚地区分出来。一类是具有文科思维的人,擅长赞叹和模糊想象,它主要依靠的是人的第一反应和直觉,比如小孩...
前后端分离,我怎么就选择了 Spring Boot + Vue 技术栈?
前两天又有小伙伴私信松哥,问题还是职业规划,Java 技术栈路线这种,实际上对于这一类问题我经常不太敢回答,每个人的情况都不太一样,而小伙伴也很少详细介绍自己的情况,大都是一两句话就把问题抛出来了,啥情况都不了解,就要指出一个方向,这实在是太难了。 因此今天我想从我学习 Spring Boot + Vue 这套技术栈的角度,来和大家聊一聊没有人指导,我是如何一步一步建立起自己的技术体系的。 线上大...
17张图带你解析红黑树的原理!保证你能看懂!
二叉查找树 由于红黑树本质上就是一棵二叉查找树,所以在了解红黑树之前,咱们先来看下二叉查找树。 二叉查找树(Binary Search Tree),也称有序二叉树(ordered binary tree),排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树: 若任意结点的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若任意结点的...
so easy! 10行代码写个"狗屁不通"文章生成器
前几天,GitHub 有个开源项目特别火,只要输入标题就可以生成一篇长长的文章。 背后实现代码一定很复杂吧,里面一定有很多高深莫测的机器学习等复杂算法 不过,当我看了源代码之后 这程序不到50行 尽管我有多年的Python经验,但我竟然一时也没有看懂 当然啦,原作者也说了,这个代码也是在无聊中诞生的,平时撸码是不写中文变量名的, 中文...
知乎高赞:中国有什么拿得出手的开源软件产品?(整理自本人原创回答)
知乎高赞:中国有什么拿得出手的开源软件产品? 在知乎上,有个问题问“中国有什么拿得出手的开源软件产品(在 GitHub 等社区受欢迎度较好的)?” 事实上,还不少呢~ 本人于2019.7.6进行了较为全面的回答,对这些受欢迎的 Github 开源项目分类整理如下: 分布式计算、云平台相关工具类 1.SkyWalking,作者吴晟、刘浩杨 等等 仓库地址: apache/skywalking 更...
MySQL数据库总结
一、数据库简介 数据库(Database,DB)是按照数据结构来组织,存储和管理数据的仓库。 典型特征:数据的结构化、数据间的共享、减少数据的冗余度,数据的独立性。 关系型数据库:使用关系模型把数据组织到数据表(table)中。现实世界可以用数据来描述。 主流的关系型数据库产品:Oracle(Oracle)、DB2(IBM)、SQL Server(MS)、MySQL(Oracle)。 数据表:数...
记一次腾讯面试:进程之间究竟有哪些通信方式?如何通信? ---- 告别死记硬背
有一次面试的时候,被问到进程之间有哪些通信方式,不过由于之前没深入思考且整理过,说的并不好。想必大家也都知道进程有哪些通信方式,可是我猜很多人都是靠着”背“来记忆的,所以今天的这篇文章,讲给大家详细着讲解他们是如何通信的,让大家尽量能够理解他们之间的区别、优缺点等,这样的话,以后面试官让你举例子,你也能够顺手拈来。 1、管道 我们来看一条 Linux 的语句 netstat -tulnp | gr...
20行Python代码爬取王者荣耀全英雄皮肤
引言 王者荣耀大家都玩过吧,没玩过的也应该听说过,作为时下最火的手机MOBA游戏,咳咳,好像跑题了。我们今天的重点是爬取王者荣耀所有英雄的所有皮肤,而且仅仅使用20行Python代码即可完成。 准备工作 爬取皮肤本身并不难,难点在于分析,我们首先得得到皮肤图片的url地址,话不多说,我们马上来到王者荣耀的官网: 我们点击英雄资料,然后随意地选择一位英雄,接着F12打开调试台,找到英雄原皮肤的图片...
傲慢与无知,请警惕伪需求的陷阱!
前言 你是否有这样的思考,与人争辩时,明明对于自己的认知和立场有着清楚的认识,同样身为人类的另一个人却完全无法接纳你的观点,这是为什么。 人类作为一个高等生物智能机器人,具备自我内存优化的能力,这一能力增加了人类的模糊处理能力从而出现了创造性,同时却削弱了人类的真理认知能力。 个体认知范围是有限的,个体只会做出认知范围内所接受的举动 青少年的时候,我常常有一种自己是特别的,是与众不同的感觉。而这种...
相关热词 c# 图片上传 c# gdi 占用内存 c#中遍历字典 c#控制台模拟dos c# 斜率 最小二乘法 c#进程延迟 c# mysql完整项目 c# grid 总行数 c# web浏览器插件 c# xml 生成xsd
立即提问