子View执行invalidate为什么父View的draw和dispatchDraw都不执行? 5C

子View执行invalidate之后,draw-ondraw-dispatchdraw。
父View只执行nvalidateChildInParent,而draw和dispatchdraw都没有执行?

3个回答

stven_king
静默加载 问的是父View没有dispatchdraw,为啥子View会执行执行draw。而不是invalidate没有回调draw。
接近 2 年之前 回复

这个要看你在什么情况下调用的invalidate,请贴一下代码,尽量详细一点。

stven_king
静默加载 一个简单的界面,点击一个按钮之后调用某个View的invalidate。这个View的父View的draw方法没执行,但该View的draw却执行了。
接近 2 年之前 回复

我自己找到了答案,原来是硬件加速的带来的。

关闭硬件加速
开启硬件加速

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
关于Android View与Drawable的问题,求高人解惑
调用`View.invalidate()`方法,就会请求`View`重新`draw()`。可是我看了`invalidate()`与相关的方法,并没有与`draw()`有直接的关系。请问`invalidate()`是如何使`View`重新`draw()`的? `Drawable.mutate()`方法为了不产生新的对象,直接返回了它自身。既然是这样,那为什么`mutate()`以后同一个图像资源能够有不同的常态(比如透明度)?在`BitmapDrawable`中在第一次`mutate()`的时候新生成一个`BitmapState`常态,后面的就是直接返回它自身了。第一次常态对象改变了倒还可以理解,可后面的我就不明白了。求高人解惑,非常感谢!
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(); }
android自定义view插入xml
自定义View代码如下。我希望把这个view插入到一个layout的xml的文件中。一直出错,错误类型是error inflating class。应该是这个View出的问题 package com.example.browserstation; import java.util.Timer; import java.util.TimerTask; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; public class touchmove extends View{ private int start_x; private final int width = MainActivity.screenWidth; private int height ; private int backwidth; private int ori_x = 0; //点击屏幕原始坐标,当前坐标和位移数据 private int ori_y = 0; private int cur_x = 0; private int cur_y = 0; private int del_x = 0; private int del_y = 0; private Bitmap bmp_back; private Bitmap bmp_bg1; private Bitmap bmp_draw0; private Bitmap bmp_draw1; private Boolean flag_move = false; private Boolean flag_temp = false; private int index = 0; private Context c; private TimerTask ttsk = new TimerTask(){ @Override public void run() { // TODO Auto-generated method stub if(flag_move)h.sendEmptyMessage(0x888); } }; final Handler h = new Handler(){ //处理信息,背景移动 public void handleMessage(Message msg){ if(msg.what == 0x888){ if(start_x < (backwidth - width-2)){ flag_temp = false; start_x += 3; }else if(start_x < backwidth - 3){ start_x += 3; flag_temp = true; }else{ if(index>0){ backwidth = bmp_back.getWidth(); index = 0; }else { backwidth = bmp_bg1.getWidth(); index += 1; } start_x = 0; flag_temp = false; flag_move = false; } } invalidate(); } }; private Timer timer; public touchmove(Context context) { super(context); c = context; bmp_back = BitmapFactory.decodeResource(getResources(), R.drawable.mainback); bmp_back = new zoompicture(bmp_back,bmp_back.getWidth(),MainActivity.screenHeight).getOutbtm(); bmp_bg1 = BitmapFactory.decodeResource(getResources(), R.drawable.bg1); bmp_bg1 = new zoompicture(bmp_bg1,bmp_bg1.getWidth(),MainActivity.screenHeight).getOutbtm(); start_x = 0; backwidth = bmp_back.getWidth(); height = MainActivity.screenHeight; bmp_draw0 = bmp_back; bmp_draw1 = bmp_back; timer = new Timer(); timer.schedule(new TimerTask(){ @Override public void run() { // TODO Auto-generated method stub if(flag_move){ h.sendEmptyMessage(0x888); } } }, 0, 100); } public touchmove(Context context, AttributeSet attrs) { super(context,attrs); // TODO Auto-generated constructor stub c = context; bmp_back = BitmapFactory.decodeResource(getResources(), R.drawable.mainback); bmp_back = new zoompicture(bmp_back,bmp_back.getWidth(),MainActivity.screenHeight).getOutbtm(); bmp_bg1 = BitmapFactory.decodeResource(getResources(), R.drawable.bg1); bmp_bg1 = new zoompicture(bmp_bg1,bmp_bg1.getWidth(),MainActivity.screenHeight).getOutbtm(); start_x = 0; backwidth = bmp_back.getWidth(); height = MainActivity.screenHeight; bmp_draw0 = bmp_back; bmp_draw1 = bmp_back; timer.schedule(new TimerTask(){ @Override public void run() { // TODO Auto-generated method stub if(flag_move){ h.sendEmptyMessage(0x888); } } }, 0, 100); } public touchmove(Context context, AttributeSet attrs, int delStyle) { super(context,attrs,delStyle); // TODO Auto-generated constructor stub c = context; bmp_back = BitmapFactory.decodeResource(getResources(), R.drawable.mainback); bmp_back = new zoompicture(bmp_back,bmp_back.getWidth(),MainActivity.screenHeight).getOutbtm(); bmp_bg1 = BitmapFactory.decodeResource(getResources(), R.drawable.bg1); bmp_bg1 = new zoompicture(bmp_bg1,bmp_bg1.getWidth(),MainActivity.screenHeight).getOutbtm(); start_x = 0; backwidth = bmp_back.getWidth(); height = MainActivity.screenHeight; bmp_draw0 = bmp_back; bmp_draw1 = bmp_back; timer.schedule(new TimerTask(){ @Override public void run() { // TODO Auto-generated method stub if(flag_move){ h.sendEmptyMessage(0x888); } } }, 0, 100); } /* (non-Javadoc) * @see android.view.View#onTouchEvent(android.view.MotionEvent) */ @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); switch(action){ case MotionEvent.ACTION_DOWN:ori_x = (int)event.getX();ori_y = (int)event.getY(); Log.v("ori_x :",""+ori_x); return true; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP:cur_x = (int)event.getX();cur_y = (int)event.getY(); del_x = cur_x - ori_x;del_y = cur_y - ori_y; if(del_x < -50){ flag_move = true; };Log.v("delx: ",""+del_x); break; } // TODO Auto-generated method stub return super.onTouchEvent(event); } /* (non-Javadoc) * @see android.view.View#onDraw(android.graphics.Canvas) */ @Override protected void onDraw(Canvas canvas) { if(!flag_temp){ switch(index){ case 0:bmp_draw0 = Bitmap.createBitmap(bmp_back,start_x,0,width,height); bmp_draw1 = bmp_draw0; canvas.drawBitmap(bmp_draw0,0,0,new Paint()); break; case 1:bmp_draw0 = Bitmap.createBitmap(bmp_bg1,start_x,0,width,height); bmp_draw1 = bmp_draw0; canvas.drawBitmap(bmp_draw0,0,0,new Paint()); break; } }else{ switch(index){ case 0:bmp_draw0 = Bitmap.createBitmap(bmp_back,start_x,0,bmp_back.getWidth()-start_x,height); bmp_draw1 = Bitmap.createBitmap(bmp_bg1,0,0,start_x+width-backwidth,height); canvas.drawBitmap(bmp_draw0,0,0,new Paint()); canvas.drawBitmap(bmp_draw1, width-bmp_draw1.getWidth(),0, new Paint()); break; case 1:bmp_draw0 = Bitmap.createBitmap(bmp_bg1,start_x,0,bmp_bg1.getWidth()-start_x,height); bmp_draw1 = Bitmap.createBitmap(bmp_back,0,0,start_x+width-backwidth,height); canvas.drawBitmap(bmp_draw0,0,0,new Paint()); canvas.drawBitmap(bmp_draw1, width-bmp_draw1.getWidth(),0, new Paint()); break; } } Log.v("v","draw1:"+bmp_draw0.getWidth()+"draw2:"+bmp_draw1.getWidth()+" strat_x"+start_x); // TODO Auto-generated method stub super.onDraw(canvas); } }
关于报错闪退的问题?有没有大神来看一眼。。。。
这是我做柱状图的代码 ``` package com.chenxi.bimquanziguankong.fragment; import android.content.Context; import android.graphics.Color; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.RelativeLayout; import com.alibaba.fastjson.JSON; import com.blankj.utilcode.util.ToastUtils; import com.chenxi.bimquanziguankong.R; import com.chenxi.bimquanziguankong.appConst.AppConst; import com.chenxi.bimquanziguankong.application.MyApplication; import com.chenxi.bimquanziguankong.common.StringAxisValueFormatter; import com.chenxi.bimquanziguankong.entity.InvestmentControlClass; import com.chenxi.bimquanziguankong.view.LineChart02View; import com.chenxi.bimquanziguankong.view.MyMarkerView; import com.github.mikephil.charting.charts.CombinedChart; import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.formatter.IAxisValueFormatter; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Random; import okhttp3.Call; import okhttp3.Callback; import okhttp3.Request; import okhttp3.Response; public class InvestmentAmountControlFragment extends BaseFragment { private View mView; RelativeLayout rl_document_list_is_null; private CombinedChart combineChart; List<InvestmentControlClass> investmentControlClasses = new ArrayList<>(); private List<String> xAxisValues = new ArrayList<>(); XAxis xAxis; YAxis axisLeft; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mView = inflater.inflate(R.layout.fragment_new_investment_amount_control, container, false); initView(mView); getxAxisValuesData(); getyAxisValuesData(); MyMarkerView myMarkerView = new MyMarkerView(getActivity(), R.layout.custom_marker_view); myMarkerView.setChartView(combineChart); combineChart.setMarker(myMarkerView); return mView; } private void initView(View mView) { rl_document_list_is_null = mView.findViewById(R.id.rl_document_list_is_null); combineChart = mView.findViewById(R.id.combineChart); combineChart.setDrawBorders(true); // 显示边界 combineChart.getDescription().setEnabled(false); // 不显示备注信息 combineChart.setPinchZoom(true); // 比例缩放 } private void getxAxisValuesData() { String url = AppConst.innerIp + "/api/" + AppConst.getProjectID() + "/InvestmentControlClass"; Request request = new Request.Builder() .url(url) .build(); MyApplication.getOkHttpClient().newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { ToastUtils.showShort("数据请求失败"); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.code() == 200) { try { String responseData = response.body().string(); investmentControlClasses = JSON.parseArray(responseData, InvestmentControlClass.class); if (investmentControlClasses.size()!=0){ for (int i = 0; i < investmentControlClasses.size(); i++) { xAxisValues.add(investmentControlClasses.get(i).getName()); } } xAxis = combineChart.getXAxis(); xAxis.setDrawGridLines(false); /*解决左右两端柱形图只显示一半的情况 只有使用CombinedChart时会出现,如果单独使用BarChart不会有这个问题*/ xAxis.setAxisMinimum(-0.5f); xAxis.setAxisMaximum(xAxisValues.size() - 0.5f); xAxis.setGranularity(1f); xAxis.setLabelCount(xAxisValues.size()); // 设置X轴标签数量 xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); // 设置X轴标签位置,BOTTOM在底部显示,TOP在顶部显示 xAxis.setValueFormatter(new StringAxisValueFormatter(xAxisValues)); axisLeft = combineChart.getAxisLeft(); // 获取左边Y轴操作类 axisLeft.setAxisMinimum(0); // 设置最小值 axisLeft.setGranularity(10); // 设置Label间隔 axisLeft.setLabelCount(10); }catch (IOException e){ e.printStackTrace(); } } else { ToastUtils.showShort("数据请求出错!500"); } } }); } private void getyAxisValuesData() { String url = AppConst.innerIp + "/api/" + AppConst.getProjectID() + "/Report/InvestmentControl"; //请求数据 Request fileRrequest = new Request.Builder() .url(url) .build(); Log.e("TAG", "柱状图地址 "+fileRrequest ); MyApplication.getOkHttpClient().newCall(fileRrequest).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { ToastUtils.showShort("数据请求失败"); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.code() == 200) { String responseData = response.body().string(); getActivity().runOnUiThread(new Runnable() { @Override public void run() { JSONArray jsonArray = null; try { jsonArray = new JSONArray(responseData); //获取柱状图数组 List<BarEntry> barEntries = new ArrayList<>(); List<Entry> lineEntry = new ArrayList<>(); if (xAxisValues.size()!=0){ for (int i = 0; i < xAxisValues.size(); i++) { List<String> list = new ArrayList<>(); for (int j = 0; j < jsonArray.length(); j++) { JSONObject jo = new JSONObject(jsonArray.get(j).toString()); if (i > 0) { list.add(jo.getString(xAxisValues.get(i))); } } String[] ary = list.toArray(new String[list.size()]); float a[] = new float[ary.length]; for (int x = 0; x < ary.length; x++) { a[x] = Float.parseFloat(ary[x]); } barEntries.add(new BarEntry(i, a)); float sum = 0; for (int z = 0; z < a.length; z++) { sum = sum + a[z]; } lineEntry.add(new Entry(i, sum)); } } //柱状图数据 BarDataSet barDataSet = new BarDataSet(barEntries, ""); barDataSet.setColors(Color.parseColor("#ae312e"), Color.parseColor("#2a3f4e"), Color.parseColor("#579199") , Color.parseColor("#be765d"), Color.parseColor("#82b49e")); BarData barData = new BarData(); barData.addDataSet(barDataSet); //折线图数据 LineDataSet lineDataSet = new LineDataSet(lineEntry, "总和"); lineDataSet.setColor(Color.parseColor("#b71c1c")); lineDataSet.setCircleColor(Color.parseColor("#b71c1c")); lineDataSet.setValueTextColor(Color.parseColor("#f44336")); lineDataSet.setLineWidth(3f); lineDataSet.setHighlightEnabled(false); LineData lineData = new LineData(); lineData.addDataSet(lineDataSet); //组和图数据 CombinedData combinedData = new CombinedData(); // 创建组合图的数据源 combinedData.setData(barData); // 添加柱形图数据源 combinedData.setData(lineData); // 添加折线图数据源 combineChart.setData(combinedData); // 为组合图设置数据源 combineChart.invalidate(); } catch (JSONException e1) { e1.printStackTrace(); } } }); } else { ToastUtils.showShort(response.message()); } } }); } } ``` 然后偶然会出现闪退的现象报错信息如下有大神帮忙看下吗感激不尽 loge报错信息 ``` 07-17 16:03:30.221 13514-13514/com.chenxi.bimquanziguankong E/CrashHandler: In thread: Thread[main,5,main] UncaughtException detected: java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0 at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255) at java.util.ArrayList.get(ArrayList.java:308) at com.github.mikephil.charting.data.DataSet.getEntryForIndex(DataSet.java:286) at com.github.mikephil.charting.utils.Transformer.generateTransformedValuesLine(Transformer.java:184) at com.github.mikephil.charting.renderer.LineChartRenderer.drawValues(LineChartRenderer.java:547) at com.github.mikephil.charting.renderer.CombinedChartRenderer.drawValues(CombinedChartRenderer.java:96) at com.github.mikephil.charting.charts.BarLineChartBase.onDraw(BarLineChartBase.java:264) at android.view.View.draw(View.java:15231) at android.view.View.updateDisplayListIfDirty(View.java:14167) at android.view.View.getDisplayList(View.java:14189) at android.view.View.draw(View.java:14959) at android.view.ViewGroup.drawChild(ViewGroup.java:3405) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198) at android.view.View.updateDisplayListIfDirty(View.java:14162) at android.view.View.getDisplayList(View.java:14189) at android.view.View.draw(View.java:14959) at android.view.ViewGroup.drawChild(ViewGroup.java:3405) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198) at android.view.View.draw(View.java:15234) at android.widget.FrameLayout.draw(FrameLayout.java:598) at android.view.View.updateDisplayListIfDirty(View.java:14167) at android.view.View.getDisplayList(View.java:14189) at android.view.View.draw(View.java:14959) at android.view.ViewGroup.drawChild(ViewGroup.java:3405) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198) at android.view.View.updateDisplayListIfDirty(View.java:14162) at android.view.View.getDisplayList(View.java:14189) at android.view.View.draw(View.java:14959) at android.view.ViewGroup.drawChild(ViewGroup.java:3405) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198) at android.view.View.draw(View.java:15234) at android.view.View.updateDisplayListIfDirty(View.java:14167) at android.view.View.getDisplayList(View.java:14189) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3389) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368) at android.view.View.updateDisplayListIfDirty(View.java:14127) at android.view.View.getDisplayList(View.java:14189) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3389) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368) at android.view.View.updateDisplayListIfDirty(View.java:14127) at android.view.View.getDisplayList(View.java:14189) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3389) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368) at android.view.View.updateDisplayListIfDirty(View.java:14127) at android.view.View.getDisplayList(View.java:14189) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3389) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368) at android.view.View.updateDisplayListIfDirty(View.java:14127) at android.view.View.getDisplayList(View.java:14189) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3389) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368) at android.view.View.updateDisplayListIfDirty(View.java:14127) at android.view.View.getDisplayList(View.java:14189) at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:273) at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:279) at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:318) at android.view.ViewRootImpl.draw(ViewRootImpl.java:2554) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2376) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2006) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1085) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5909) at android.view.C 07-17 16:03:30.247 13514-13514/com.chenxi.bimquanziguankong E/AndroidRuntime: FATAL EXCEPTION: main Process: com.chenxi.bimquanziguankong, PID: 13514 java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0 at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255) at java.util.ArrayList.get(ArrayList.java:308) at com.github.mikephil.charting.data.DataSet.getEntryForIndex(DataSet.java:286) at com.github.mikephil.charting.utils.Transformer.generateTransformedValuesLine(Transformer.java:184) at com.github.mikephil.charting.renderer.LineChartRenderer.drawValues(LineChartRenderer.java:547) at com.github.mikephil.charting.renderer.CombinedChartRenderer.drawValues(CombinedChartRenderer.java:96) at com.github.mikephil.charting.charts.BarLineChartBase.onDraw(BarLineChartBase.java:264) at android.view.View.draw(View.java:15231) at android.view.View.updateDisplayListIfDirty(View.java:14167) at android.view.View.getDisplayList(View.java:14189) at android.view.View.draw(View.java:14959) at android.view.ViewGroup.drawChild(ViewGroup.java:3405) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198) at android.view.View.updateDisplayListIfDirty(View.java:14162) at android.view.View.getDisplayList(View.java:14189) at android.view.View.draw(View.java:14959) at android.view.ViewGroup.drawChild(ViewGroup.java:3405) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198) at android.view.View.draw(View.java:15234) at android.widget.FrameLayout.draw(FrameLayout.java:598) at android.view.View.updateDisplayListIfDirty(View.java:14167) at android.view.View.getDisplayList(View.java:14189) at android.view.View.draw(View.java:14959) at android.view.ViewGroup.drawChild(ViewGroup.java:3405) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198) at android.view.View.updateDisplayListIfDirty(View.java:14162) at android.view.View.getDisplayList(View.java:14189) at android.view.View.draw(View.java:14959) at android.view.ViewGroup.drawChild(ViewGroup.java:3405) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198) at android.view.View.draw(View.java:15234) at android.view.View.updateDisplayListIfDirty(View.java:14167) at android.view.View.getDisplayList(View.java:14189) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3389) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368) at android.view.View.updateDisplayListIfDirty(View.java:14127) at android.view.View.getDisplayList(View.java:14189) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3389) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368) at android.view.View.updateDisplayListIfDirty(View.java:14127) at android.view.View.getDisplayList(View.java:14189) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3389) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368) at android.view.View.updateDisplayListIfDirty(View.java:14127) at android.view.View.getDisplayList(View.java:14189) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3389) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368) at android.view.View.updateDisplayListIfDirty(View.java:14127) at android.view.View.getDisplayList(View.java:14189) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3389) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368) at android.view.View.updateDisplayListIfDirty(View.java:14127) at android.view.View.getDisplayList(View.java:14189) at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:273) at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:279) at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:318) at android.view.ViewRootImpl.draw(ViewRootImpl.java:2554) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2376) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2006) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1085) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5909) ```
android保存当前view变成bitmap,并保存bitmap到本地
做了一个保存当前view成bitmap图片的项目,但最终报如下错误,找了半天也找不到解决之法。 --------------------------------- public static Bitmap getBitmapByView(ScrollView scrollView, HorizontalScrollView hsv) { int w = 0; int h = 0; Bitmap bitmap = null; // 获取scrollview实际高度 for (int i = 0; i < scrollView.getChildCount(); i++) { h += scrollView.getChildAt(i).getHeight(); scrollView.getChildAt(i).setBackgroundColor(Color.parseColor("#ffffff")); } // 获取HorizontalScrollView实际宽度 for (int i = 0; i < hsv.getChildCount(); i++) { w += hsv.getChildAt(i).getWidth(); hsv.getChildAt(i).setBackgroundColor(Color.parseColor("#ffffff")); } // 创建对应大小的bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565); final Canvas canvas = new Canvas(bitmap); scrollView.draw(canvas); hsv.draw(canvas); return bitmap; } /** * 压缩图片 * * @param image * @return */ public static Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 image.compress(Bitmap.CompressFormat.JPEG, 100, baos); // 把压缩后的数据baos存放到ByteArrayInputStream中 ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray()); // 把ByteArrayInputStream数据生成图片 Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null); return bitmap; } /** * 保存到sdcard * * @param b * @return */ public static String savePic(Bitmap b) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.US); File outfile = new File("/sdcard/image"); // 如果文件不存在,则创建一个新文件 if (!outfile.isDirectory()) { try { outfile.mkdir(); } catch (Exception e) { e.printStackTrace(); } } String fname = outfile + "/" + sdf.format(new Date()) + ".png"; FileOutputStream fos = null; try { fos = new FileOutputStream(fname); if (null != fos) { b.compress(Bitmap.CompressFormat.PNG, 90, fos); fos.flush(); fos.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return fname; } --------------------------------------------- 09-28 14:31:11.181 23514-23514/com.bonc.ms.main I/ViewRootImpl: finishMotionEvent: handled = true stage=10: View Post IME stage,inputElapseTime=0 eventTime = 867860380 downTime = 867860380 title= com.bonc.ms.main/com.bonc.ms.main.develop.FourGDevelopActivity 09-28 14:31:11.287 23514-23514/com.bonc.ms.main V/SettingsInterface: invalidate [system]: current 4765 != cached 0 09-28 14:31:11.289 23514-23514/com.bonc.ms.main D/ActivityThread: holder:android.app.IActivityManager$ContentProviderHolder@30ba67e, holder.provider:android.content.ContentProviderProxy@c2477df 09-28 14:31:11.398 23514-23520/com.bonc.ms.main W/art: Suspending all threads took: 58.163ms 09-28 14:31:12.773 23514-23724/com.bonc.ms.main D/skia: jpeg_decoder mode 1, colorType 4, w 7907, h 4586, sample 1, bsLength 0!! 09-28 14:31:13.227 23514-23724/com.bonc.ms.main D/skia: jpeg_decoder finish successfully, L:1934!!! 09-28 14:31:13.229 23514-23724/com.bonc.ms.main W/System.err: java.io.FileNotFoundException: /sdcard/image/2016-09-28_14-31-13.png: open failed: ENOENT (No such file or directory) 09-28 14:31:13.231 23514-23724/com.bonc.ms.main W/System.err: at libcore.io.IoBridge.open(IoBridge.java:487) 09-28 14:31:13.231 23514-23724/com.bonc.ms.main W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:87) 09-28 14:31:13.231 23514-23724/com.bonc.ms.main W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:127) 09-28 14:31:13.231 23514-23724/com.bonc.ms.main W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:116) 09-28 14:31:13.231 23514-23724/com.bonc.ms.main W/System.err: at com.bonc.ms.tools.ScreenShot.savePic(ScreenShot.java:110) 09-28 14:31:13.231 23514-23724/com.bonc.ms.main W/System.err: at com.bonc.ms.main.develop.FourGDevelopActivity$3.run(FourGDevelopActivity.java:153) 09-28 14:31:13.231 23514-23724/com.bonc.ms.main W/System.err: at java.lang.Thread.run(Thread.java:818) 09-28 14:31:13.231 23514-23724/com.bonc.ms.main W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory) 09-28 14:31:13.232 23514-23724/com.bonc.ms.main W/System.err: at libcore.io.Posix.open(Native Method) 09-28 14:31:13.232 23514-23724/com.bonc.ms.main W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186) 09-28 14:31:13.232 23514-23724/com.bonc.ms.main W/System.err: at libcore.io.IoBridge.open(IoBridge.java:473) 09-28 14:31:13.232 23514-23724/com.bonc.ms.main W/System.err: ... 6 more
android程序,eclipse没报错,但是运行会意外停止
本人刚开始学习android,跟着书写了个程序,这个程序是会有一个东西随着手指拖动而移动,编译完没有问题,但是在手机上运行的时候却是意外停止,代码和书上写的一模一样,求大神指导 DrawView.java的代码: /** * */ package com.example.customview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; /** * Description: * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a> * <br/>Copyright (C), 2001-2014, Yeeku.H.Lee * <br/>This program is protected by copyright laws. * <br/>Program Name: * <br/>Date: * @author Yeeku.H.Lee kongyeeku@163.com * @version 1.0 */ public class DrawView extends View { public float currentX = 40; public float currentY = 50; // 定义、并创建画笔 Paint p = new Paint(); public DrawView(Context context) { super(context); } public DrawView(Context context , AttributeSet set) { super(context ,set); } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); // 设置画笔的颜色 p.setColor(Color.RED); // 绘制一个小圆(作为小球) canvas.drawCircle(currentX, currentY, 15, p); } // 为该组件的触碰事件重写事件处理方法 @Override public boolean onTouchEvent(MotionEvent event) { // 修改currentX、currentY两个属性 currentX = event.getX(); currentY = event.getY(); // 通知当前组件重绘自己 invalidate(); // 返回true表明该处理方法已经处理该事件 return true; } } CustomView.java的代码: package com.example.customview; import android.app.Activity; import android.os.Bundle; import android.widget.LinearLayout; /** * Description: * <br/>site: <a href="http://www.crazyit.org">crazyit.org</a> * <br/>Copyright (C), 2001-2014, Yeeku.H.Lee * <br/>This program is protected by copyright laws. * <br/>Program Name: * <br/>Date: * @author Yeeku.H.Lee kongyeeku@163.com * @version 1.0 */ public class CustomView extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.custom_view); // 获取布局文件中的LinearLayout容器 LinearLayout root = (LinearLayout) findViewById(R.id.root); // 创建DrawView组件 final DrawView draw = new DrawView(this); // 设置自定义组件的最大宽度、高度 draw.setMinimumWidth(300); draw.setMinimumHeight(500); root.addView(draw); } } custom_view.xml的代码: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/root"> </LinearLayout>
android 怎么实现实时GPS监控
我在android studio中模拟了一个Java服务器,连续发送经纬度数据。客户端这边接收数据后要怎么实现在地图上实时显示经纬度确立的点?(java服务器发送数据,建了一个Service接收数据,通过广播发送到Activity,Activity显示地图,同时接收广播数据,在onRecieve方法中showOverlay)在真机测试时,新建了Activity,通过一个Button启动Service,数据传递正常,通过另一个Button启动Activitiy,程序闪退 经纬度数据我是按GPGGA的格式写的,SDK用的是supermap iclient for android,自己试过在地图上标注指定点,坐标转换应该没关系 这个是onRecieve里的代码 ``` Bundle bundle=intent.getExtras(); X2 = bundle.getDouble("x"); Y2 = bundle.getDouble("y"); mapView.getController().setCenter(new Point2D(X2,Y2)); point2D2.x=X2; point2D2.y=Y2; showOverlay(); ``` 地图的话是supermap Iserver发布的网址URL ``` private static final String DEFAULT_URL="http://192.168.1.12:8090/iserver/services/map-ElecChart5/rest/maps/CN484217_22000"; protected MapView mapView; mapView=(MapView)this.findViewById(R.id.mapview) LayerView layerView=new LayerView(this); layerView.setURL(DEFAULT_URL); mapView.setBuiltInZoomControls(true); mapView.addLayer(layerView); ``` 这个是闪退的Activity代码 ```public class GpsActivity extends AppCompatActivity{ private static final String DEFAULT_URL="http://192.168.1.12:8090/iserver/services/map-ElecChart5/rest/maps/CN484217_22000"; MapView mapView; private Button buttonEnd; MyReceiver receiver = null; private Button buttonStart; double X2; double Y2; Point2D point2D2 = new Point2D(X2, Y2); @Override public void onCreate( Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_gps); buttonStart = (Button) findViewById(R.id.button_start); buttonEnd = (Button) findViewById(R.id.button_stop); buttonEnd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { stopService(new Intent(GpsShowActivity.this, GpsService.class)); finish(); } }); buttonStart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startService(new Intent(GpsActivity.this, GpsService.class)); } }); receiver=new MyReceiver(); IntentFilter filter=new IntentFilter(); filter.addAction("com.example.badius.iservertest.GpsService"); GpsActivity.this.registerReceiver(receiver,filter); } public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Bundle bundle=intent.getExtras(); X2 = bundle.getDouble("x"); Y2 = bundle.getDouble("y"); mapView.getController().setCenter(new Point2D(X2,Y2)); point2D2.x=X2; point2D2.y=Y2; showOverlay(); } } private void showOverlay(){ DefaultItemizedOverlay overlay=new DefaultItemizedOverlay(getResources().getDrawable(R.mipmap.point_marker)); OverlayItem overlayItem1=new OverlayItem(point2D2,"A","A"); overlay.addItem(overlayItem1); mapView.getOverlays().add(new CustomOverlay()); mapView.getOverlays().add(overlay); mapView.invalidate(); } class CustomOverlay extends Overlay { @Override public void draw(Canvas canvas, MapView mapView, boolean shadow){ super.draw(canvas,mapView,shadow); Paint paint=new Paint(); Point point=mapView.getProjection().toPixels(new Point2D(X2,Y2),null); paint.setTextSize(24); paint.setStrokeWidth(0.8f); paint.setARGB(255,255,0,0); paint.setStyle(Paint.Style.FILL_AND_STROKE); canvas.drawText("当前位置",point.x,point.y,paint); } } } ``` 我是门外汉一个,还有什么描述不清楚的麻烦再提示,谢谢!
在Bitmap或者OVERLAYING按钮上如何动态的创建一个按钮
我想在视图的 BITMAP或者OVERLAYING按钮上面创建一个按钮。我创建了一个数字签名,签名后,我需要点击一个按钮来保存。我使用的如下代码 public class FingerPaint extends GraphicsActivity implements OnClickListener { private TextView pauseButton; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new MyView(this)); Capture_SignatureActivity.writeLog("In FingerPaint class"); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setColor(0xFF003F87); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(1); } private Paint mPaint; public void colorChanged(int color) { Capture_SignatureActivity.writeLog("In color changed"); mPaint.setColor(color); } public class MyView extends View{ private static final float MINP = 0.25f; private static final float MAXP = 0.75f; private Bitmap mBitmap; private Canvas mCanvas; private Path mPath; private Paint mBitmapPaint; private Bitmap overlayDefault; private Bitmap overlay; private Canvas c2; private Paint pTouch; private float X = -100; private float Y = -100; public MyView(Context c) { super(c); Capture_SignatureActivity.writeLog("In MyVIEW"); mPath = new Path(); mBitmapPaint = new Paint(Paint.DITHER_FLAG); mBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher); overlayDefault = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher); overlay = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher).copy(Config.ARGB_8888, true); c2 = new Canvas(overlay); pTouch = new Paint(Paint.ANTI_ALIAS_FLAG); pTouch.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT)); pTouch.setColor(Color.TRANSPARENT); pTouch.setMaskFilter(new BlurMaskFilter(15, Blur.NORMAL)); pTouch.setMaskFilter(startActivity(FingerPaint.this, Capture_SignatureActivity.class)); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); System.out.println("w-->"+w+"-->"+"h--"+h+"-->"+"oldw-->"+oldh+"oldw-->"+oldw); Capture_SignatureActivity.writeLog("In onSizeChanged"); mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); } @Override protected void onDraw(Canvas canvas) { Capture_SignatureActivity.writeLog("In onDraw"); canvas.drawColor(0xFFFFFFFF); canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); canvas.drawPath(mPath, mPaint); c2.drawBitmap(overlayDefault, 0, 0, null); //exclude this line to show all as you draw c2.drawCircle(X , Y , 80, pTouch); //draw the overlay over the background canvas.drawBitmap(overlay, 0, 0, null); } private float mX, mY; private static final float TOUCH_TOLERANCE = 4; private void touch_start(float x, float y) { Capture_SignatureActivity.writeLog("In touch_start"); mPath.reset(); mPath.moveTo(x, y); mX = x; mY = y; System.out.println("---- " +mX); } private void touch_move(float x, float y) { Capture_SignatureActivity.writeLog("In touch_Move"); 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() { Capture_SignatureActivity.writeLog("In 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) { Capture_SignatureActivity.writeLog("In touch_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 onClick(View v) { //In myView startActivity(new Intent(FingerPaint.this, Capture_SignatureActivity.class)); } } public void onClick(View v) { //onCreate } @Override public boolean onCreateOptionsMenu(android.view.Menu menu) { super.onCreateOptionsMenu(menu); menu.add(0, 1, 0 , "Clear Screen"); menu.add(0, 2, 0 , "Exit Screen"); return true; } @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { switch(item.getItemId()) { case 1: startActivity(new Intent(this, FingerPaint.class)); break; case 2: startActivity(new Intent(this, Capture_SignatureActivity.class)); break; } return super.onMenuItemSelected(featureId, item); } } 创建了图像,但是不能开启activity。怎么解决这个问题呢?
android 中的签名问题
在android应用程序中用户在程序的表格中做了签名,签名必须要编辑,清除,保存,我做了保存和清除,但是编辑这项功能却不能运行。我的代码如下,怎么修改呢? mContent = (LinearLayout) findViewById(R.id.linearLayout); mSignature = new signature(this, null); mSignature.setBackgroundColor(Color.WHITE); mContent.addView(mSignature, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); mClear = (Button)findViewById(R.id.clear); mGetSign = (Button)findViewById(R.id.getsign); mGetSign.setEnabled(false); mCancel = (Button)findViewById(R.id.cancel); mView = mContent; mClear.setOnClickListener(new OnClickListener() { public void onClick(View v) { Log.v("log_tag", "Panel Cleared"); mSignature.clear(); mGetSign.setEnabled(false); } }); mGetSign.setOnClickListener(new OnClickListener() { public void onClick(View v) { Log.v("log_tag", "Panel Saved"); mView.setDrawingCacheEnabled(true); mSignature.save(mView); Bundle b = new Bundle(); b.putString("status", "done"); b.putParcelable("data", mBitmap); Intent intent = new Intent(); intent.putExtras(b); setResult(RESULT_OK,intent); finish(); } }); mCancel.setOnClickListener(new OnClickListener() { public void onClick(View v) { Log.v("log_tag", "Panel Canceled"); Bundle b = new Bundle(); b.putString("status", "cancel"); Intent intent = new Intent(); intent.putExtras(b); setResult(RESULT_OK,intent); finish(); } }); } @Override protected void onDestroy() { Log.w("GetSignature", "onDestory"); super.onDestroy(); } public class signature extends View { private static final float STROKE_WIDTH = 5f; private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2; private Paint paint = new Paint(); private Path path = new Path(); private float lastTouchX; private float lastTouchY; private final RectF dirtyRect = new RectF(); public signature(Context context, AttributeSet attrs) { super(context, attrs); paint.setAntiAlias(true); paint.setColor(Color.BLACK); paint.setStyle(Paint.Style.STROKE); paint.setStrokeJoin(Paint.Join.ROUND); paint.setStrokeWidth(STROKE_WIDTH); } public void save(View v) { Log.v("log_tag", "Width: " + v.getWidth()); Log.v("log_tag", "Height: " + v.getHeight()); if(mBitmap == null) { mBitmap = Bitmap.createBitmap (mContent.getWidth(), mContent.getHeight(), Bitmap.Config.RGB_565);; } Canvas canvas = new Canvas(mBitmap); try { FileOutputStream mFileOutStream = new FileOutputStream(mypath); v.draw(canvas); mBitmap.compress(Bitmap.CompressFormat.PNG, 90, mFileOutStream); mFileOutStream.flush(); mFileOutStream.close(); // String url = Images.Media.insertImage(getContentResolver(), mBitmap, "title", null); // Log.v("log_tag","url: " + url); //In case you want to delete the file //boolean deleted = mypath.delete(); //Log.v("log_tag","deleted: " + mypath.toString() + deleted); //If you want to convert the image to string use base64 converter } catch(Exception e) { Log.v("log_tag", e.toString()); } } public void clear() { path.reset(); invalidate(); } @Override protected void onDraw(Canvas canvas) { canvas.drawPath(path, paint); } @Override public boolean onTouchEvent(MotionEvent event) { float eventX = event.getX(); float eventY = event.getY(); mGetSign.setEnabled(true); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: path.moveTo(eventX, eventY); lastTouchX = eventX; lastTouchY = eventY; return true; case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_UP: resetDirtyRect(eventX, eventY); int historySize = event.getHistorySize(); for (int i = 0; i < historySize; i++) { float historicalX = event.getHistoricalX(i); float historicalY = event.getHistoricalY(i); expandDirtyRect(historicalX, historicalY); path.lineTo(historicalX, historicalY); } path.lineTo(eventX, eventY); break; default: debug("Ignored touch event: " + event.toString()); return false; } invalidate((int) (dirtyRect.left - HALF_STROKE_WIDTH), (int) (dirtyRect.top - HALF_STROKE_WIDTH), (int) (dirtyRect.right + HALF_STROKE_WIDTH), (int) (dirtyRect.bottom + HALF_STROKE_WIDTH)); lastTouchX = eventX; lastTouchY = eventY; return true; } private void debug(String string){ } private void expandDirtyRect(float historicalX, float historicalY) { if (historicalX < dirtyRect.left) { dirtyRect.left = historicalX; } else if (historicalX > dirtyRect.right) { dirtyRect.right = historicalX; } if (historicalY < dirtyRect.top) { dirtyRect.top = historicalY; } else if (historicalY > dirtyRect.bottom) { dirtyRect.bottom = historicalY; } } private void resetDirtyRect(float eventX, float eventY) { dirtyRect.left = Math.min(lastTouchX, eventX); dirtyRect.right = Math.max(lastTouchX, eventX); dirtyRect.top = Math.min(lastTouchY, eventY); dirtyRect.bottom = Math.max(lastTouchY, eventY); } }
按下按钮后擦除器没有调用
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`
“Unfortunately, app name has stopped.”android设备或者是模拟器
我在根据一些教程来创建app,当我想要运行app的时候,没有显示错误,但是在emulator显示"Unfortunately, Viewfinder blabla has stopped." 代码: AndroidManifest.xml file <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.viewfinderee368" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".ViewfinderEE368" android:label="@string/app_name" android:screenOrientation="landscape"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="6"/> <uses-permission android:name="android.permission.CAMERA"/> <uses-feature android:name="android.hardware.camera"/> <uses-feature android:name="android.hardware.camera.autofocus"/> </manifest> src/.java file package com.example.viewfinderee368; import java.io.IOException; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.hardware.Camera; import android.hardware.Camera.PreviewCallback; import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.view.ViewGroup.LayoutParams; // ---------------------------------------------------------------------- public class ViewfinderEE368 extends Activity { private Preview mPreview; private DrawOnTop mDrawOnTop; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 隐藏窗口标题H getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); requestWindowFeature(Window.FEATURE_NO_TITLE); //创建预览视图然后将它设置为activity的目录 //创建DrawOnTop视图. mDrawOnTop = new DrawOnTop(this); mPreview = new Preview(this, mDrawOnTop); setContentView(mPreview); addContentView(mDrawOnTop, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); } } //---------------------------------------------------------------------- class DrawOnTop extends View { Bitmap mBitmap; Paint mPaintBlack; Paint mPaintYellow; Paint mPaintRed; Paint mPaintGreen; Paint mPaintBlue; byte[] mYUVData; int[] mRGBData; int mImageWidth, mImageHeight; int[] mRedHistogram; int[] mGreenHistogram; int[] mBlueHistogram; double[] mBinSquared; public DrawOnTop(Context context) { super(context); mPaintBlack = new Paint(); mPaintBlack.setStyle(Paint.Style.FILL); mPaintBlack.setColor(Color.BLACK); mPaintBlack.setTextSize(25); mPaintYellow = new Paint(); mPaintYellow.setStyle(Paint.Style.FILL); mPaintYellow.setColor(Color.YELLOW); mPaintYellow.setTextSize(25); mPaintRed = new Paint(); mPaintRed.setStyle(Paint.Style.FILL); mPaintRed.setColor(Color.RED); mPaintRed.setTextSize(25); mPaintGreen = new Paint(); mPaintGreen.setStyle(Paint.Style.FILL); mPaintGreen.setColor(Color.GREEN); mPaintGreen.setTextSize(25); mPaintBlue = new Paint(); mPaintBlue.setStyle(Paint.Style.FILL); mPaintBlue.setColor(Color.BLUE); mPaintBlue.setTextSize(25); mBitmap = null; mYUVData = null; mRGBData = null; mRedHistogram = new int[256]; mGreenHistogram = new int[256]; mBlueHistogram = new int[256]; mBinSquared = new double[256]; for (int bin = 0; bin < 256; bin++) { mBinSquared[bin] = ((double)bin) * bin; } // bin } @Override protected void onDraw(Canvas canvas) { if (mBitmap != null) { int canvasWidth = canvas.getWidth(); int canvasHeight = canvas.getHeight(); int newImageWidth = canvasWidth; int newImageHeight = canvasHeight; int marginWidth = (canvasWidth - newImageWidth)/2; // 从YUV转换成RGB decodeYUV420SP(mRGBData, mYUVData, mImageWidth, mImageHeight); // 画位图 // mBitmap.setPixels(mRGBData, 0, mImageWidth, 0, 0, // mImageWidth, mImageHeight); // Rect src = new Rect(0, 0, mImageWidth, mImageHeight); // Rect dst = new Rect(marginWidth, 0, // canvasWidth-marginWidth, canvasHeight); // canvas.drawBitmap(mBitmap, src, dst, mPaintBlack); // 画黑色边缘 // canvas.drawRect(0, 0, marginWidth, canvasHeight, mPaintBlack); // canvas.drawRect(canvasWidth - marginWidth, 0, // canvasWidth, canvasHeight, mPaintBlack); // 计算直方图 calculateIntensityHistogram(mRGBData, mRedHistogram, mImageWidth, mImageHeight, 0); calculateIntensityHistogram(mRGBData, mGreenHistogram, mImageWidth, mImageHeight, 1); calculateIntensityHistogram(mRGBData, mBlueHistogram, mImageWidth, mImageHeight, 2); // 计算平均值 double imageRedMean = 0, imageGreenMean = 0, imageBlueMean = 0; double redHistogramSum = 0, greenHistogramSum = 0, blueHistogramSum = 0; for (int bin = 0; bin < 256; bin++) { imageRedMean += mRedHistogram[bin] * bin; redHistogramSum += mRedHistogram[bin]; imageGreenMean += mGreenHistogram[bin] * bin; greenHistogramSum += mGreenHistogram[bin]; imageBlueMean += mBlueHistogram[bin] * bin; blueHistogramSum += mBlueHistogram[bin]; } // bin imageRedMean /= redHistogramSum; imageGreenMean /= greenHistogramSum; imageBlueMean /= blueHistogramSum; double imageRed2ndMoment = 0, imageGreen2ndMoment = 0, imageBlue2ndMoment = 0; for (int bin = 0; bin < 256; bin++) { imageRed2ndMoment += mRedHistogram[bin] * mBinSquared[bin]; imageGreen2ndMoment += mGreenHistogram[bin] * mBinSquared[bin]; imageBlue2ndMoment += mBlueHistogram[bin] * mBinSquared[bin]; } // bin imageRed2ndMoment /= redHistogramSum; imageGreen2ndMoment /= greenHistogramSum; imageBlue2ndMoment /= blueHistogramSum; double imageRedStdDev = Math.sqrt( imageRed2ndMoment - imageRedMean*imageRedMean ); double imageGreenStdDev = Math.sqrt( imageGreen2ndMoment - imageGreenMean*imageGreenMean ); double imageBlueStdDev = Math.sqrt( imageBlue2ndMoment - imageBlueMean*imageBlueMean ); // 画平均值 String imageMeanStr = "Mean (R,G,B): " + String.format("%.4g", imageRedMean) + ", " + String.format("%.4g", imageGreenMean) + ", " + String.format("%.4g", imageBlueMean); canvas.drawText(imageMeanStr, marginWidth+10-1, 30-1, mPaintBlack); canvas.drawText(imageMeanStr, marginWidth+10+1, 30-1, mPaintBlack); canvas.drawText(imageMeanStr, marginWidth+10+1, 30+1, mPaintBlack); canvas.drawText(imageMeanStr, marginWidth+10-1, 30+1, mPaintBlack); canvas.drawText(imageMeanStr, marginWidth+10, 30, mPaintYellow); // 画标准差 String imageStdDevStr = "Std Dev (R,G,B): " + String.format("%.4g", imageRedStdDev) + ", " + String.format("%.4g", imageGreenStdDev) + ", " + String.format("%.4g", imageBlueStdDev); canvas.drawText(imageStdDevStr, marginWidth+10-1, 60-1, mPaintBlack); canvas.drawText(imageStdDevStr, marginWidth+10+1, 60-1, mPaintBlack); canvas.drawText(imageStdDevStr, marginWidth+10+1, 60+1, mPaintBlack); canvas.drawText(imageStdDevStr, marginWidth+10-1, 60+1, mPaintBlack); canvas.drawText(imageStdDevStr, marginWidth+10, 60, mPaintYellow); // 画红色直方图 float barMaxHeight = 3000; float barWidth = ((float)newImageWidth) / 256; float barMarginHeight = 2; RectF barRect = new RectF(); barRect.bottom = canvasHeight - 200; barRect.left = marginWidth; barRect.right = barRect.left + barWidth; for (int bin = 0; bin < 256; bin++) { float prob = (float)mRedHistogram[bin] / (float)redHistogramSum; barRect.top = barRect.bottom - Math.min(80,prob*barMaxHeight) - barMarginHeight; canvas.drawRect(barRect, mPaintBlack); barRect.top += barMarginHeight; canvas.drawRect(barRect, mPaintRed); barRect.left += barWidth; barRect.right += barWidth; } // bin // 画绿色直方图 barRect.bottom = canvasHeight - 100; barRect.left = marginWidth; barRect.right = barRect.left + barWidth; for (int bin = 0; bin < 256; bin++) { barRect.top = barRect.bottom - Math.min(80, ((float)mGreenHistogram[bin])/((float)greenHistogramSum) * barMaxHeight) - barMarginHeight; canvas.drawRect(barRect, mPaintBlack); barRect.top += barMarginHeight; canvas.drawRect(barRect, mPaintGreen); barRect.left += barWidth; barRect.right += barWidth; } // bin // 画蓝色直方图 barRect.bottom = canvasHeight; barRect.left = marginWidth; barRect.right = barRect.left + barWidth; for (int bin = 0; bin < 256; bin++) { barRect.top = barRect.bottom - Math.min(80, ((float)mBlueHistogram[bin])/((float)blueHistogramSum) * barMaxHeight) - barMarginHeight; canvas.drawRect(barRect, mPaintBlack); barRect.top += barMarginHeight; canvas.drawRect(barRect, mPaintBlue); barRect.left += barWidth; barRect.right += barWidth; } // bin } //结束条件语句 super.onDraw(canvas); } // 结束onDraw方法 static public void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; for (int j = 0, yp = 0; j < height; j++) { int uvp = frameSize + (j >> 1) * width, u = 0, v = 0; for (int i = 0; i < width; i++, yp++) { int y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { v = (0xff & yuv420sp[uvp++]) - 128; u = (0xff & yuv420sp[uvp++]) - 128; } int y1192 = 1192 * y; int r = (y1192 + 1634 * v); int g = (y1192 - 833 * v - 400 * u); int b = (y1192 + 2066 * u); if (r < 0) r = 0; else if (r > 262143) r = 262143; if (g < 0) g = 0; else if (g > 262143) g = 262143; if (b < 0) b = 0; else if (b > 262143) b = 262143; rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); } } } static public void decodeYUV420SPGrayscale(int[] rgb, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; for (int pix = 0; pix < frameSize; pix++) { int pixVal = (0xff & ((int) yuv420sp[pix])) - 16; if (pixVal < 0) pixVal = 0; if (pixVal > 255) pixVal = 255; rgb[pix] = 0xff000000 | (pixVal << 16) | (pixVal << 8) | pixVal; } } static public void calculateIntensityHistogram(int[] rgb, int[] histogram, int width, int height, int component) { for (int bin = 0; bin < 256; bin++) { histogram[bin] = 0; } // bin if (component == 0) // red { for (int pix = 0; pix < width*height; pix += 3) { int pixVal = (rgb[pix] >> 16) & 0xff; histogram[ pixVal ]++; } // pix } else if (component == 1) // green { for (int pix = 0; pix < width*height; pix += 3) { int pixVal = (rgb[pix] >> 8) & 0xff; histogram[ pixVal ]++; } // pix } else // blue { for (int pix = 0; pix < width*height; pix += 3) { int pixVal = rgb[pix] & 0xff; histogram[ pixVal ]++; } // pix } } } // ---------------------------------------------------------------------- class Preview extends SurfaceView implements SurfaceHolder.Callback { SurfaceHolder mHolder; Camera mCamera; DrawOnTop mDrawOnTop; boolean mFinished; Preview(Context context, DrawOnTop drawOnTop) { super(context); mDrawOnTop = drawOnTop; mFinished = false; // 安装SurfaceHolder.Callback以便当下垫面被创建和销毁的时候我们能够获得通知 mHolder = getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { mCamera = Camera.open(); try { mCamera.setPreviewDisplay(holder); mCamera.setPreviewCallback(new PreviewCallback() { public void onPreviewFrame(byte[] data, Camera camera) { if ( (mDrawOnTop == null) || mFinished ) return; if (mDrawOnTop.mBitmap == null) { // 初始化draw-on-top companion Camera.Parameters params = camera.getParameters(); mDrawOnTop.mImageWidth = params.getPreviewSize().width; mDrawOnTop.mImageHeight = params.getPreviewSize().height; mDrawOnTop.mBitmap = Bitmap.createBitmap(mDrawOnTop.mImageWidth, mDrawOnTop.mImageHeight, Bitmap.Config.RGB_565); mDrawOnTop.mRGBData = new int[mDrawOnTop.mImageWidth * mDrawOnTop.mImageHeight]; mDrawOnTop.mYUVData = new byte[data.length]; } System.arraycopy(data, 0, mDrawOnTop.mYUVData, 0, data.length); mDrawOnTop.invalidate(); } }); } catch (IOException exception) { mCamera.release(); mCamera = null; } } public void surfaceDestroyed(SurfaceHolder holder) { // 但给我们返回的时候,Surface将被摧毁,所以停止预览 // 因为CameraDevice object不是共享的对象,所以当activity停止的时候要释放它。这个很重要。 mFinished = true; mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.release(); mCamera = null; } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // 现在这个大小是知道的,设置相机参数然后开始预览 Camera.Parameters parameters = mCamera.getParameters(); parameters.setPreviewSize(320, 240); parameters.setPreviewFrameRate(15); parameters.setSceneMode(Camera.Parameters.SCENE_MODE_NIGHT); parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); mCamera.setParameters(parameters); mCamera.startPreview(); } } 我尝试在真机下和模拟器下运行,但是错误都一样 LogCat 11-20 02:50:38.943: E/AndroidRuntime(614): FATAL EXCEPTION: main 11-20 02:50:38.943: E/AndroidRuntime(614): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.viewfinderee368/com.example.viewfinderee368.ViewfinderEE368}: android.util.AndroidRuntimeException: requestFeature() must be called before adding content 11-20 02:50:38.943: E/AndroidRuntime(614): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059) 11-20 02:50:38.943: E/AndroidRuntime(614): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) 11-20 02:50:38.943: E/AndroidRuntime(614): at android.app.ActivityThread.access$600(ActivityThread.java:130) 11-20 02:50:38.943: E/AndroidRuntime(614): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) 11-20 02:50:38.943: E/AndroidRuntime(614): at android.os.Handler.dispatchMessage(Handler.java:99) 11-20 02:50:38.943: E/AndroidRuntime(614): at android.os.Looper.loop(Looper.java:137) 11-20 02:50:38.943: E/AndroidRuntime(614): at android.app.ActivityThread.main(ActivityThread.java:4745) 11-20 02:50:38.943: E/AndroidRuntime(614): at java.lang.reflect.Method.invokeNative(Native Method) 11-20 02:50:38.943: E/AndroidRuntime(614): at java.lang.reflect.Method.invoke(Method.java:511) 11-20 02:50:38.943: E/AndroidRuntime(614): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 11-20 02:50:38.943: E/AndroidRuntime(614): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 11-20 02:50:38.943: E/AndroidRuntime(614): at dalvik.system.NativeStart.main(Native Method) 11-20 02:50:38.943: E/AndroidRuntime(614): Caused by: android.util.AndroidRuntimeException: requestFeature() must be called before adding content 11-20 02:50:38.943: E/AndroidRuntime(614): at com.android.internal.policy.impl.PhoneWindow.requestFeature(PhoneWindow.java:215) 11-20 02:50:38.943: E/AndroidRuntime(614): at android.app.Activity.requestWindowFeature(Activity.java:3225) 11-20 02:50:38.943: E/AndroidRuntime(614): at com.example.viewfinderee368.ViewfinderEE368.onCreate(ViewfinderEE368.java:52) 11-20 02:50:38.943: E/AndroidRuntime(614): at android.app.Activity.performCreate(Activity.java:5008) 11-20 02:50:38.943: E/AndroidRuntime(614): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079) 11-20 02:50:38.943: E/AndroidRuntime(614): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023) 11-20 02:50:38.943: E/AndroidRuntime(614): ... 11 more
android模拟时钟 秒针卡顿(有时候秒针会不走,然后下一秒会跳动三个格子)
``` package custom.analog.clock; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.BroadcastReceiver; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.os.CountDownTimer; import android.os.Handler; import android.text.format.Time; import android.util.AttributeSet; import android.view.View; import java.util.TimeZone; public class AnalogClock extends View { public AnalogClock(Context context) { super(context); } private Time mCalendar; private Drawable mHourHand; private Drawable mMinuteHand; private Drawable mSecondHand; private Drawable mDial; private int mDialWidth; private int mDialHeight; private boolean mAttached; private final Handler mHandler = new Handler(); private float mMinutes; private float mHour; private boolean mChanged; Context mContext; public AnalogClock(Context context, AttributeSet attrs) { this(context, attrs, 0); } public AnalogClock(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); Resources r = context.getResources(); mContext = context; mDial = r.getDrawable(R.drawable.clock_dial); mHourHand = r.getDrawable(R.drawable.clock_hour); mMinuteHand = r.getDrawable(R.drawable.clock_minute); mSecondHand = r.getDrawable(R.drawable.clockgoog_minute); mCalendar = new Time(); mDialWidth = mDial.getIntrinsicWidth(); mDialHeight = mDial.getIntrinsicHeight(); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (!mAttached) { mAttached = true; IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_TIME_TICK); filter.addAction(Intent.ACTION_TIME_CHANGED); filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); getContext().registerReceiver(mIntentReceiver, filter, null, mHandler); } mCalendar = new Time(); onTimeChanged(); counter.start(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mAttached) { counter.cancel(); getContext().unregisterReceiver(mIntentReceiver); mAttached = false; } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); float hScale = 1.0f; float vScale = 1.0f; if (widthMode != MeasureSpec.UNSPECIFIED && widthSize < mDialWidth) { hScale = (float) widthSize / (float) mDialWidth; } if (heightMode != MeasureSpec.UNSPECIFIED && heightSize < mDialHeight) { vScale = (float) heightSize / (float) mDialHeight; } float scale = Math.min(hScale, vScale); setMeasuredDimension( resolveSize((int) (mDialWidth * scale), widthMeasureSpec), resolveSize((int) (mDialHeight * scale), heightMeasureSpec)); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mChanged = true; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); boolean changed = mChanged; if (changed) { mChanged = false; } boolean seconds = mSeconds; if (seconds) { mSeconds = false; } int availableWidth = 200; int availableHeight = 200; int x = availableWidth / 2; int y = availableHeight / 2; final Drawable dial = mDial; int w = dial.getIntrinsicWidth(); int h = dial.getIntrinsicHeight(); boolean scaled = false; if (availableWidth < w || availableHeight < h) { scaled = true; float scale = Math.min((float) availableWidth / (float) w, (float) availableHeight / (float) h); canvas.save(); canvas.scale(scale, scale, x, y); } if (changed) { dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2)); } dial.draw(canvas); canvas.save(); canvas.rotate(mHour / 12.0f * 360.0f, x, y); final Drawable hourHand = mHourHand; if (changed) { w = hourHand.getIntrinsicWidth(); h = hourHand.getIntrinsicHeight(); hourHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2)); } hourHand.draw(canvas); canvas.restore(); canvas.save(); canvas.rotate(mMinutes / 60.0f * 360.0f, x, y); final Drawable minuteHand = mMinuteHand; if (changed) { w = minuteHand.getIntrinsicWidth(); h = minuteHand.getIntrinsicHeight(); minuteHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2)); } minuteHand.draw(canvas); canvas.restore(); canvas.save(); canvas.rotate(mSecond, x, y); if (seconds) { w = mSecondHand.getIntrinsicWidth(); h = mSecondHand.getIntrinsicHeight(); mSecondHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2)); } mSecondHand.draw(canvas); /*********************************************/ canvas.restore(); if (scaled) { canvas.restore(); } } MyCount counter = new MyCount(10000, 1000); public class MyCount extends CountDownTimer { public MyCount(long millisInFuture, long countDownInterval) { super(millisInFuture, countDownInterval); } @Override public void onFinish() { counter.start(); } @Override public void onTick(long millisUntilFinished) { mCalendar.setToNow(); int second = mCalendar.second; mSecond = 6.0f * second; mSeconds = true; AnalogClock.this.invalidate(); } } boolean mSeconds = false; float mSecond = 0; private void onTimeChanged() { mCalendar.setToNow(); int hour = mCalendar.hour; int minute = mCalendar.minute; int second = mCalendar.second; mMinutes = minute + second / 60.0f; mHour = hour + mMinutes / 60.0f; mChanged = true; } private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) { String tz = intent.getStringExtra("time-zone"); mCalendar = new Time(TimeZone.getTimeZone(tz).getID()); } onTimeChanged(); invalidate(); } }; } ``` ``` ```
关于 Movie播放gif图片的问题
播放与屏幕尺寸大小差不多的图片,用movie显示还正常,但是播放尺寸过大的图片, 不会自动按照屏幕的比例缩小进行显示,就是只能显示出一部分,其他的都看不见, 哪位知道怎么改一下就可以了。。。 这是我的代码 public class GifView extends View { //表示开始播放gif图片的绝对时间 private long movieStart = 0; //movie对象管理gif图片里面的多个帧 private Movie movie; public GifView(Context context, AttributeSet attrs) { super(context, attrs); } public GifView(Context context) { super(context); } @Override protected void onDraw(Canvas canvas) { if (movie != null) { long currentTime = System.currentTimeMillis(); // 第一次画 if (movieStart == 0) { movieStart = currentTime; } int duration = movie.duration(); int relTime = (int) ((currentTime - movieStart) % duration); movie.setTime(relTime); movie.draw(canvas, (getWidth()-movie.width())/2,(getHeight()-movie.height())/2); // 强制重绘 invalidate(); } //如果只想播放一次,只需判断currentTime-movieStart的值大于duration就不重绘即可 super.onDraw(canvas); } public void setMovie(String path){ if(path.equals("")){ movie=null; }else{ movie=Movie.decodeFile(path); } } }
安卓中 surfaceview中显示三个折线图,可左右拖动查看未显示的图形
我在做安卓surfaceview的时候,要加载显示3条折线,但只有一条折线的时候,正常拖动都没问题,一旦显示3条折线,拖动就不能显示预期的折线,拖动后显示的是一片空白,除了最右边一点折线 自定义类 ``` public class MultiLineChartSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable { /** surface持有者 */ private SurfaceHolder mHolder; /** 当前画布 */ private Canvas mCanvas; /** 是否开始绘画 */ private boolean mIsDrawing; /** 坐标轴举例view边框的距离 */ private static final int DEFAULT_PADDING = 20; /** 默认宽度设置为400dp */ private static final int DEFAULT_WIDTH = 450; /** 默认高度设置为400dp */ private static final int DEFAULT_HEIGHT = 300; /** 默认折线的颜色 */ private static final int DEFAULT_LINE_COLOR = Color.GREEN; /** 默认x轴的颜色 */ private static final int DEFAULT_X_LINE_COLOR = 0xffEBEBEB; /** 默认Y轴的颜色 */ private static final int DEFAULT_Y_LINE_COLOR = 0xffEBEBEB; /** 默认折线的宽度 */ private static final int DEFAULT_LINE_WIDTH = 1; /** 默认x轴的量程 */ private static final int DEFAULT_X_RANGE = 1000; /** 默认y轴的量程 */ private static final int DEFAULT_Y_RANGE = 1000; /** 默认x轴每个刻度代表的单位 */ private static final int DEFAULT_X_UNIT = 50; /** 默认y轴每个刻度代表的单位 */ private static final int DEFAULT_Y_UNIT = 50; /** 每个刻度的高度 */ private static final int DEFAULT_SCALE_HEIGHT = 4; /** 默认x轴尽头箭头的长度 */ private static final int DEFAULT_X_BLANK = 20; /** 默认y轴尽头箭头的长度 */ private static final int DEFAULT_Y_BLANK = 20; /** x轴的单位 */ private int mXUnit; /** 每个y轴的单位的高度 */ private int mYUnit; /** 折线的颜色 */ private int mLineColor; /** x轴的颜色 */ private int mXLineColor; /** y轴的颜色 */ private int mYLineColor; /** 折线的宽度 */ private int mLineWidth; /** x轴的量程 */ private int mXRange; /** y轴的量程 */ private int mYRange; /** 绘制折线的画笔 */ private Paint mLinePaint; /** 绘制坐标的画笔 */ private Paint mCoordinatePaint; /** view的宽度 */ private int mWidth; /** View的高度 */ private int mHeight; /** 坐标轴距离view边距的间距 */ private int mPaddint; /** 刻度的高度 */ private int mScaleHeight; /** y轴的实际高度 */ private int mAxisHeight; /** x轴的实际高度 */ private int mAxisWidth; /** X轴最后一个竖线与箭头的空格 */ private int mXBlank; /** Y轴最后一个竖线与箭头的空格 */ private int mYBlank; /** 每个x轴刻度的宽度 */ private int mXScaleWidth; /** 每个y轴刻度的宽度 */ private int mYScaleWidth; /** 外部的list,用来存放折线上的值 */ private List<List<Integer>> mLines; /** 最后一次点击的x坐标 */ private int lastX; /** 偏移量,用来实现平滑移动 */ private int mOffset = 0; /** 移动速度,用来实现速度递减 */ private int mSpeed = 0; /** 是否触摸屏幕 */ private boolean mIsTouch = false; /** 时间计数器,用来快速滚动时候减速 */ private int time = 0; /** 移动时候X方向上的速度 */ private double xVelocity = 0; /** 是否可以滚动,当不在范围时候不可以滚动 */ private boolean isScroll = true; /** x轴上的格子数量 */ private int mXScaleNum; /** y轴上的格子数量 */ private int mYScaleNum; public MultiLineChartSurfaceView(Context context) { this(context, null); } public MultiLineChartSurfaceView(Context context, AttributeSet attrs) { this(context, attrs, -1); } public MultiLineChartSurfaceView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } /** 设置一些变量的尺寸 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthMode == MeasureSpec.AT_MOST) { mWidth = dp2px(getContext(), DEFAULT_WIDTH); } else { mWidth = Math.max(widthSize, dp2px(getContext(), DEFAULT_WIDTH)); } if (heightMode == MeasureSpec.AT_MOST) { mHeight = dp2px(getContext(), DEFAULT_HEIGHT); } else { mHeight = Math.max(heightSize, dp2px(getContext(), DEFAULT_HEIGHT)); } setMeasuredDimension(mWidth, mHeight); } /** 初始化surfaceView操作 */ private void init() { mHolder = getHolder(); mHolder.addCallback(this); // 设置可以获取焦点 setFocusable(true); // 进入触摸输入模式后,该控件是否还有获得焦点的能力 setFocusableInTouchMode(true); // 是否保持屏幕常亮 this.setKeepScreenOn(true); // 为部分成员变量赋初值,可以写成自定义属性 mLineColor = DEFAULT_LINE_COLOR; mLineWidth = dp2px(getContext(), DEFAULT_LINE_WIDTH); mXLineColor = DEFAULT_X_LINE_COLOR; mYLineColor = DEFAULT_Y_LINE_COLOR; mXRange = DEFAULT_X_RANGE; mYRange = DEFAULT_Y_RANGE; mXUnit = DEFAULT_X_UNIT; mYUnit = DEFAULT_Y_UNIT; mPaddint = dp2px(getContext(), DEFAULT_PADDING); mScaleHeight = dp2px(getContext(), DEFAULT_SCALE_HEIGHT); mLinePaint = new Paint(); mCoordinatePaint = new Paint(); } /** 子线程,循环绘制折线 */ @Override public void run() { // 如果处于绘画状态,那么就开始绘制 while (mIsDrawing) { // 判断是否处于边缘状态 setSpeedCut(); // 绘制方法 draw(); } } /** 具体的绘制方法 */ private void draw() { try { long start = System.currentTimeMillis(); // 获取并锁定画布 mCanvas = mHolder.lockCanvas(); // 设置画布背景为白色 mCanvas.drawColor(0xff000000); // 绘制坐标轴 drawAxis(); // 绘制曲线 drawLine(); long end = System.currentTimeMillis(); if (end - start < 50) { Thread.sleep(50 - (end - start)); } } catch (Exception e) { e.printStackTrace(); } finally { if (mCanvas != null) { // 保证每次都将绘制的内容提交到服务器 mHolder.unlockCanvasAndPost(mCanvas); } } } /** 绘制坐标系 */ private void drawAxis() { mCanvas.save(); // 移动坐标原点到左下角 mCanvas.translate(mPaddint, mHeight - mPaddint); // 画线 drawXYLine(); // 绘制坐标轴上的刻度 // 绘制xy轴末端的箭头 drawXYScale(); mCanvas.restore(); } /** 绘制折线 */ private void drawLine() { mCanvas.save(); mCanvas.translate(mPaddint, mHeight - mPaddint); // 设置画笔属性 mLinePaint.setAntiAlias(true); mLinePaint.setStrokeWidth(3); mLinePaint.setColor(mLineColor); mLinePaint.setStyle(Style.STROKE); //x轴每次的步进 int xInterval=(int)mXScaleWidth/5; // 如果折线集合不为空 if (mLines != null && mLines.size() > 0) { for(int k=0;k<mLines.size();k++) { // 循环绘制所有线条 for (int i = 1; i < mLines.get(k).size(); i++) { // 上一个点的xy坐标 int previousY = (int) (mLines.get(k).get(i - 1) * 1.0 / mYRange * (mAxisHeight - mYBlank)); int previousX = (i - 1) * mXScaleWidth + mOffset; // 当前点的xy坐标 int thisY = (int) (mLines.get(k).get(i) * 1.0 / mYRange * (mAxisHeight - mYBlank)); int thisX = i * xInterval + mOffset; // 保证只绘制坐标轴范围内的部分 if (previousX > 0 && previousX < mAxisWidth - mXBlank && thisX > 0 && thisX < mAxisWidth - mXBlank) // 两个坐标连线 mCanvas.drawLine(previousX, -previousY, thisX, -thisY, mLinePaint); } } } mCanvas.restore(); } /** * 设置快速滚动时,末尾的减速 */ private void setSpeedCut() { if (!mIsTouch && isScroll) { // 通过当前速度计算所对应的偏移量 mOffset = mOffset + mSpeed; setOffsetRange(); } // 每次偏移量的计算 if (mSpeed != 0) { time++; mSpeed = (int) (xVelocity + time * time * (xVelocity / 1600.0) - (xVelocity / 20.0) * time); } else { time = 0; mSpeed = 0; } } /** * 绘制x、y轴 */ private void drawXYLine() { mAxisWidth = mWidth - mPaddint; mAxisHeight = mHeight - 2 * mPaddint; mCoordinatePaint.setStrokeWidth(mLineWidth); mCoordinatePaint.setAntiAlias(true); // 绘制x轴 mCoordinatePaint.setColor(mXLineColor); mCanvas.drawLine(0, 0, mAxisWidth, 0, mCoordinatePaint); // 绘制y轴 mCoordinatePaint.setColor(mYLineColor); mCanvas.drawLine(0, 0, 0, -mAxisHeight, mCoordinatePaint); } /** 绘制刻度线和箭头 */ private void drawXYScale() { // 画y轴的刻度 mYScaleNum = mYRange / mYUnit; mYScaleWidth = (int) (mAxisHeight * 1.0 / mYScaleNum); mCoordinatePaint.setTextSize(30); for (int i = 0; i < mYScaleNum; i++) { mCanvas.drawLine(0, -mYScaleWidth * (i + 1), mAxisWidth, -mYScaleWidth * (i + 1), mCoordinatePaint); String yText = ""; if (i== 3||i==9||i==15) { yText = "0"; mCanvas.drawText(yText,-30,-mYScaleWidth * (i + 1),mCoordinatePaint); } else if (i == 1||i==7||i==13) { yText = "-1"; mCanvas.drawText(yText,-30,-mYScaleWidth * (i + 1),mCoordinatePaint); } else if(i == 5||i==11||i==17){ yText = "1"; mCanvas.drawText(yText,-30,-mYScaleWidth * (i + 1),mCoordinatePaint); } } // 画x轴的刻度 // x轴的分割线数量 mXScaleNum=mAxisWidth/mYScaleWidth; // 每个刻度的宽度 mXScaleWidth =mYScaleWidth;// (int) ((mAxisWidth - mXBlank) * 1.0 / mXScaleNum); for (int i = 0; i < mXScaleNum; i++) { mCanvas.drawLine(mXScaleWidth * (i + 1), 0, mXScaleWidth * (i + 1), -mAxisHeight, mCoordinatePaint); if(i!=0&&(i+1)%5==0) { mCanvas.drawText(String.valueOf((i+1) / 5), mXScaleWidth * (i + 1), 30, mCoordinatePaint); } } } /** 对偏移量进行边界值判定 */ private void setOffsetRange() { int offsetMax = -mXScaleWidth * (mLines.size()) + (mXScaleWidth * mXScaleNum + 2); int offsetMin = 2 * mXScaleWidth; if (mOffset > offsetMin) { isScroll = false; mOffset = offsetMin; } else if (mOffset < offsetMax) {// 如果划出最大值范围 isScroll = false; mOffset = offsetMax; } else { isScroll = true; } } @Override public boolean onTouchEvent(MotionEvent event) { int rawX = (int) (event.getRawX()); // 计算当前速度 VelocityTracker velocityTracker = VelocityTracker.obtain(); velocityTracker.addMovement(event); // 计算速度的单位时间 velocityTracker.computeCurrentVelocity(50); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 记录触摸点坐标 lastX = rawX; mIsTouch = true; break; case MotionEvent.ACTION_MOVE: // 计算便宜量 int offsetX = rawX - lastX; // 在当前偏移量的基础上增加偏移量 mOffset = mOffset + offsetX; setOffsetRange(); // 偏移量修改后下次重绘会有变化 lastX = rawX; // 获取X方向上的速度 xVelocity = velocityTracker.getXVelocity(); mSpeed = (int) xVelocity; break; case MotionEvent.ACTION_UP: mIsTouch = false; break; } // 计算完成后回收内存 velocityTracker.clear(); velocityTracker.recycle(); return true; } /** * 画布创建时候执行的方法 * * @param holder */ @Override public void surfaceCreated(SurfaceHolder holder) { // 开始绘画 mIsDrawing = true; // 启动绘画线程 new Thread(this).start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } /** * 画布销毁时候执行的方法 */ @Override public void surfaceDestroyed(SurfaceHolder holder) { // 停止绘画 mIsDrawing = false; } /** * 外部用来设置折线数据的方法 */ public void setSingleLine(List<Integer> lines) { if(this.mLines==null) mLines=new ArrayList<List<Integer>>() ; this.mLines.add(lines); invalidate(); } /** * 外部用来设置折线数据的方法 */ public void setMultiLines(List<List<Integer>> lines) { if(this.mLines==null) mLines=new ArrayList<List<Integer>>() ; this.mLines=lines; invalidate(); } /** dp转化为px工具 */ private int dp2px(Context context, int dp) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics()); } } ``` activity中 ``` public class MainActivity extends Activity { private MultiLineChartSurfaceView mllcv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); List<List<Integer>> mLinesList = getData(); mllcv = (MultiLineChartSurfaceView) findViewById(R.id.mllcv); mllcv.setMultiLines(mLinesList); } private List<List<Integer>> getData() { List<List<Integer>> mLineList = new ArrayList<List<Integer>>(); List<Integer> line1 = new ArrayList<Integer>(); List<Integer> line2 = new ArrayList<Integer>(); for (int i = 0; i < 600; i++) { line1.add(550 + (int) (Math.random() * 200)); line2.add(550 - (int) (Math.random() * 200)); } mLineList.add(line1); mLineList.add(line2); return mLineList; } } ``` Layout ``` <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.bisa.linetest.MainActivity" > <com.bisa.linetest.MultiLineChartSurfaceView android:id="@+id/mllcv" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout> ```
小弟有个androi动画的问题,困扰我太久了,求大神解惑
我自定义了一个View,在鼠标点击处画一个小球,利用ObjectAnimator和PropertyValuesHolder设置动画效果,为什么设置x,y属性动画正常,小球能沿着坐标轴一定,设置 alpha和scale就不起作用,这玩意是怎么知道我写的X,Y就是让他在坐标轴上移动,但是他为什么不认识alpha和scale,还是我写的有问题,代码如下 package com.example.mrwuchao.newballtest; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RadialGradient; import android.graphics.Shader; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.shapes.OvalShape; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.view.animation.AccelerateInterpolator; import android.widget.Button; import android.widget.RelativeLayout; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { private float BALL_SIZE = 50f; ArrayList<ShapeHolder> arrayList = new ArrayList<>(); // Button button; /*出现问题 * 自定义的View可以使用想x,y属性让小球移动,但是使用alpha或者scale就没有效果 * objectAnimator是怎么识别这些属性的,写出一个字符串,他是怎么判断要执行什么动画的?*/ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RelativeLayout re = (RelativeLayout)findViewById(R.id.re); re.addView(new MyView(this)); // button = (Button)findViewById(R.id.button); } public class MyView extends View implements ValueAnimator.AnimatorUpdateListener { public MyView(Context context) { super(context); setBackgroundColor(Color.WHITE); } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() != MotionEvent.ACTION_DOWN && event.getAction() != MotionEvent.ACTION_MOVE) { return false; } ShapeHolder newBall = addBall(event.getX(), event.getY()); PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("x",event.getX(),600f,200f); PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("alpha",1.0f,0f); ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(newBall,p1,p2); oa.setDuration(2000); // oa.setInterpolator(new AccelerateInterpolator()); oa.addUpdateListener(this); oa.start(); // ObjectAnimator oa = ObjectAnimator.ofFloat(newBall,"x",600f); // ObjectAnimator ob = ObjectAnimator.ofFloat(newBall,"y",600f); // // ob.addUpdateListener(this); // // AnimatorSet animatorSet = new AnimatorSet(); // animatorSet.play(oa).with(ob); // animatorSet.setDuration(2000); // animatorSet.start(); return true; } private ShapeHolder addBall(float x, float y) { OvalShape circle = new OvalShape(); circle.resize(BALL_SIZE, BALL_SIZE); ShapeDrawable drawable = new ShapeDrawable(circle); ShapeHolder shapeHolder = new ShapeHolder(drawable); shapeHolder.setX(x-BALL_SIZE/2); shapeHolder.setY(y-BALL_SIZE/2); shapeHolder.setAlpha(1.0f); Paint paint = drawable.getPaint(); int[] color = new int[]{Color.GRAY, Color.BLUE}; RadialGradient gradient = new RadialGradient(40f, 15f, BALL_SIZE, color, null, Shader.TileMode.CLAMP); paint.setShader(gradient); //paint.setColor(Color.RED); shapeHolder.setPaint(paint); arrayList.add(shapeHolder); return shapeHolder; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (ShapeHolder sh : arrayList) { canvas.save(); canvas.translate(sh.getX(),sh.getY()); sh.getD().draw(canvas); canvas.restore(); } } @Override public void onAnimationUpdate(ValueAnimator animation) { this.invalidate(); } } } 包装类 package com.example.mrwuchao.newballtest; import android.graphics.Paint; import android.graphics.drawable.ShapeDrawable; /** * Created by Mr.wuchao on 2016/6/8. */ public class ShapeHolder { public void setDrawable(ShapeDrawable drawable) { this.d = drawable; } ShapeDrawable d; Paint paint; float alpha = 1.0f; float x,y; public ShapeHolder(ShapeDrawable drawable) { this.d = drawable; } public ShapeDrawable getD() { return d; } public void setD(ShapeDrawable d) { this.d = d; } public float getAlpha() { return alpha; } public void setAlpha(float alpha) { this.alpha = alpha; } public float getX() { return x; } public void setX(float x) { this.x = x; } public Paint getPaint() { return paint; } public void setPaint(Paint paint) { this.paint = paint; } public float getY() { return y; } public void setY(float y) { this.y = y; } }
Fresco加载网络图片部分设备出现显示部分图片为黑色并崩溃
1.在使用Fresco显示网络图片在天猫魔盒M17设备时,出现部分图片显示为黑色,且一段时间后程序崩溃。 相关代码: public class TvSimpleDraweeView extends SimpleDraweeView implements ShimmerViewBase { private float mCornerRadius; private Paint mPaint; private Path mPath; private Drawable mForeground; private Rect paddingRect; private ShimmerViewHelper shimmerViewHelper; public TvSimpleDraweeView(Context context) { this(context, null); } public TvSimpleDraweeView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TvSimpleDraweeView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(attrs); shimmerViewHelper = new ShimmerViewHelper(this, new Paint(), attrs); shimmerViewHelper.setPrimaryColor(0x66ffffff); shimmerViewHelper.setReflectionColor(0x01ffffff); setWillNotDraw(false); } private void init(AttributeSet attrs) { if (attrs != null) { TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable .TvSimpleDraweeView); mCornerRadius = ta.getDimension(R.styleable.TvSimpleDraweeView_tvCornerRadius, 0f); mForeground = ta.getDrawable(R.styleable.TvSimpleDraweeView_tvForegroundDrawable); ta.recycle(); } mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); mPath = new Path(); if (mForeground == null) { mForeground = ContextCompat.getDrawable(getContext(), R.drawable.rect_common_cursor); } paddingRect = new Rect(); mForeground.getPadding(paddingRect); setFocusable(true); setClickable(true); } @Override public void draw(Canvas canvas) { int count = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG); super.draw(canvas); canvas.drawPath(mPath, mPaint); canvas.restoreToCount(count); if (hasFocus() || showFocusForced) { mForeground.draw(canvas); } if (shimmerViewHelper != null) { shimmerViewHelper.onDraw(canvas); } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { mPath.reset(); mPath.addRoundRect(new RectF(0, 0, w, h), mCornerRadius, mCornerRadius, Path.Direction.CW); mForeground.setBounds(-paddingRect.left, -paddingRect.top, w + paddingRect.right, h + paddingRect.bottom); if (shimmerViewHelper != null) { shimmerViewHelper.onSizeChanged(); } } public void setCornerRadius(float cornerRadius) { mCornerRadius = cornerRadius; } public void setResImage(int resId) { setImageURI(new Uri.Builder().scheme(UriUtil.LOCAL_RESOURCE_SCHEME).path(String.valueOf (resId)).build()); } private boolean showFocusForced = false; public void forceShowFocus() { showFocusForced = true; invalidate(); } public void hideFocus() { showFocusForced = false; invalidate(); } @Override public float getGradientX() { return shimmerViewHelper.getGradientX(); } @Override public void setGradientX(float gradientX) { shimmerViewHelper.setGradientX(gradientX); } @Override public boolean isShimmering() { return shimmerViewHelper.isShimmering(); } @Override public void setShimmering(boolean isShimmering) { shimmerViewHelper.setShimmering(isShimmering); } @Override public boolean isSetUp() { return shimmerViewHelper.isSetUp(); } @Override public void setAnimationSetupCallback(ShimmerViewHelper.AnimationSetupCallback callback) { shimmerViewHelper.setAnimationSetupCallback(callback); } @Override public int getPrimaryColor() { return shimmerViewHelper.getPrimaryColor(); } @Override public void setPrimaryColor(int primaryColor) { shimmerViewHelper.setPrimaryColor(primaryColor); } @Override public int getReflectionColor() { return shimmerViewHelper.getReflectionColor(); } @Override public void setReflectionColor(int reflectionColor) { shimmerViewHelper.setReflectionColor(reflectionColor); } private Shimmer mShimmer; @Override protected void onFocusChanged(boolean gainFocus, int direction, @Nullable Rect previouslyFocusedRect) { super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); if (gainFocus) { showShimmer(); } else { hideShimmer(); } } public void hideShimmer() { if (null != mShimmer && mShimmer.isAnimating()) { mShimmer.cancel(); } } public void showShimmer() { hideShimmer(); mShimmer = new Shimmer(); mShimmer.setRepeatCount(0); mShimmer.setDuration(1000); mShimmer.start(this); } } public class ColumnBoxView1 extends TvSimpleDraweeView implements ColumnBoxView, View.OnClickListener { public ColumnBoxView1(Context context) { super(context); init(); } public ColumnBoxView1(Context context, AttributeSet attrs) { super(context, attrs); init(); } public ColumnBoxView1(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } ColumnBoxInfo mColumnBoxInfo; private void init() { setCornerRadius(6f); getHierarchy().setPlaceholderImage(R.drawable.ic_holder, ScalingUtils.ScaleType.FIT_XY); setOnClickListener(this); } @Override public void setColumnBoxInfo(ColumnBoxInfo columnBoxInfo) { mColumnBoxInfo = columnBoxInfo; setImageURI(columnBoxInfo.getCoverPath()); // SimpleDraweeViewUtils.setBlurImage(this,columnBoxInfo.getCoverPath()); } @Override protected void onFocusChanged(boolean gainFocus, int direction, @Nullable Rect previouslyFocusedRect) { super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); if (gainFocus) { bringToFront(); } } @Override public void onClick(View v) { ColumnBoxUtils.onClick(mColumnBoxInfo, getContext()); } } 尝试把setImageURI方法替换为 public static void setBlurImage(SimpleDraweeView draweeView, String path) { ImageRequest request = ImageRequestBuilder. newBuilderWithSource(Uri.parse(path)) .setPostprocessor(new BlurPostprocessor(draweeView.getContext())) .build(); PipelineDraweeController controller = (PipelineDraweeController) Fresco .newDraweeControllerBuilder() .setImageRequest(request) .setOldController(draweeView.getController()) .build(); draweeView.setController(controller); } 后,原本正常显示的图片变得模糊,且还是部分图片显示黑色。 ![图片说明](https://img-ask.csdn.net/upload/201812/24/1545647357_157891.jpg)
MFC使用CMemory封装类来实现透明位图出错
问题描述: 想要实现的效果是在屏幕出现一只飞舞的蝴蝶(带有透明色背景位图),使用了CMemory封装类 来实现,虽然可以使蝴蝶飞动,但最终蝴蝶图片的背景还是没有去除掉, Memory.h头文件 ``` #pragma once #include "afxwin.h" #ifndef __MEMDC_H__ #define __MEMDC_H__ class CMemoryDC :public CDC { CSize m_size; public: void BitTrans( int nXDest, // 目标起点X int nYDest, // 目标起点Y int nWidthDest, // 目标宽度 int nHeightDest,// 目标高度 CDC* pDC, // 目标DC int nXSrc, // 来源起点X int nYSrc, // 来源起点Y COLORREF crTrans// 透明色 ) { CMemoryDC dcImage(nWidthDest, nHeightDest, pDC);//临时DC CBitmap bmpMask; bmpMask.CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL); // 创建单色掩码位图 CDC dcMask;//掩码DC dcMask.CreateCompatibleDC(pDC); dcMask.SelectObject(bmpMask); //将载入位图的内存DC中的位图,拷贝到临时DC中 dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, this, nXSrc, nYSrc, SRCCOPY); // 设置临时DC的透明色 dcImage.SetBkColor(crTrans); //掩码DC的透明区域为白色其它区域为黑色 dcMask.BitBlt(0, 0, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCCOPY); //临时DC透明区域为黑色,其它区域保持不变 dcImage.SetBkColor(RGB(0, 0, 0)); dcImage.SetTextColor(RGB(255, 255, 255)); dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND); // 目标DC透明部分保持屏幕不变,其它部分变成黑色 pDC->SetBkColor(RGB(255, 255, 255)); pDC->SetTextColor(RGB(0, 0, 0)); pDC->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND); pDC->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCPAINT); } void StretchTrans( int nXDest, // 目标起点X int nYDest, // 目标起点Y int nWidthDest, // 目标宽度 int nHeightDest, // 目标高度 CDC* pDC, // 目标DC int nXSrc, // 来源起点X int nYSrc, // 来源起点Y int nWidthSrc, // 来源宽度 int nHeightSrc, // 来源高度 COLORREF crTrans // 透明色 ) { CMemoryDC dcImage(nWidthDest, nHeightDest, pDC);//临时DC CBitmap bmpMask; // 创建单色掩码位图 bmpMask.CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL); CDC dcMask; dcMask.CreateCompatibleDC(pDC); dcMask.SelectObject(bmpMask); // 将载入位图的内存DC中的位图,拷贝到临时DC中 if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc) dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, this, nXSrc, nYSrc, SRCCOPY); else dcImage.StretchBlt(0, 0, nWidthDest, nHeightDest, this, nXSrc, nYSrc, nWidthSrc, nHeightSrc, SRCCOPY); // 设置临时DC的透明色 dcImage.SetBkColor(crTrans); //掩码DC的透明区域为白色其它区域为黑色 dcMask.BitBlt(0, 0, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCCOPY); //临时DC透明区域为黑色,其它区域保持不变 dcImage.SetBkColor(RGB(0, 0, 0)); dcImage.SetTextColor(RGB(255, 255, 255)); dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND); // 目标DC透明部分保持屏幕不变,其它部分变成黑色 pDC->SetBkColor(RGB(255, 255, 255)); pDC->SetTextColor(RGB(0, 0, 0)); pDC->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND); pDC->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCPAINT); } CMemoryDC() { m_size.cx = m_size.cy = 0; } //从资源中加载位图 BOOL LoadBitmap(UINT nBitmapID, CDC* pDC = NULL) { CBitmap bitmap; bitmap.LoadBitmap(nBitmapID); BITMAP bm; bitmap.GetBitmap(&bm); m_size.cx = bm.bmWidth; m_size.cy = bm.bmHeight; CreateCompatibleDC(pDC); SelectObject(bitmap); return TRUE; } CMemoryDC(UINT nBitmapID, CDC* pDC = NULL) { LoadBitmap(nBitmapID, pDC); } //从.bmp文件中加载位图 BOOL LoadBitmap(LPCTSTR szBitmapFile, CDC* pDC = NULL) { HBITMAP hBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(), szBitmapFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); BITMAP bm; GetObject(hBitmap, sizeof(bm), &bm); m_size.cx = bm.bmWidth; m_size.cy = bm.bmHeight; CreateCompatibleDC(pDC); SelectObject(hBitmap); return TRUE; } CMemoryDC(LPCTSTR szBitmapFile, CDC* pDC = NULL) { LoadBitmap(szBitmapFile, pDC); } //创建一张空白内存画布 BOOL Create(int cx, int cy, CDC* pDC = NULL) { CreateCompatibleDC(pDC); CBitmap bitmap; if (pDC) bitmap.CreateCompatibleBitmap(pDC, cx, cy); else bitmap.CreateCompatibleBitmap(&CClientDC(NULL), cx, cy); m_size.cx = cx; m_size.cy = cy; SelectObject(bitmap); return TRUE; } CMemoryDC(int cx, int cy, CDC* pDC = NULL) { Create(cx, cy, pDC); } //摧毁 BOOL DeleteDC() { if (!GetSafeHdc()) return TRUE; CBitmap * pBitmap = GetCurrentBitmap(); pBitmap->DeleteObject(); return CDC::DeleteDC(); } ~CMemoryDC() { DeleteDC(); } inline int Width() { return m_size.cx; } inline int Height() { return m_size.cy; } void CMemoryDC::BitRgn(CRgn &rgn,/*目标区域*/COLORREF crTrans/*透明色*/) { //根据当前位图和透明色生成一个不规则区域 int i = 0, j = 0; rgn.CreateRectRgn(0, 0, 0, 0); while (i < m_size.cx) { j = 0; while (j < m_size.cy) { if (GetPixel(i, j) - crTrans) { //如果不是透明色就在区域内增加一个点 CRgn r; r.CreateRectRgn(i, j, i + 1, j + 1); rgn.CombineRgn(&rgn, &r, RGN_OR); } ++j; } ++i; } } }; \#endif //__MEMDC_H__ ``` 主对话框头文件:FlyRgnDlg.h ``` // FlyRgnDlg.h : header file // #pragma once #include "MemDC.h" // CFlyRgnDlg dialog class CFlyRgnDlg : public CDialogEx { // Construction public: enum { FLY_CNT = 7 }; CMemoryDC m_dc[FLY_CNT]; CRgn m_rgn[FLY_CNT]; int m_nIndex; //当前帧数 CPoint m_pos; //当前位置 public: CFlyRgnDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data #ifdef AFX_DESIGN_TIME enum { IDD = IDD_FLYRGN_DIALOG }; #endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // Implementation protected: HICON m_hIcon; // Generated message map functions virtual BOOL OnInitDialog(); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: afx_msg void OnTimer(UINT_PTR nIDEvent); void OnDraw(CDC* pDC); afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnNcPaint(); }; ``` 主对话框cpp文件:FlyRgnDlg.cpp ``` // FlyRgnDlg.cpp : implementation file // #include "stdafx.h" #include "FlyRgn.h" #include "FlyRgnDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CFlyRgnDlg dialog #define TRANSCOLOR RGB(0,0,0) CFlyRgnDlg::CFlyRgnDlg(CWnd* pParent /*=NULL*/) : CDialogEx(IDD_FLYRGN_DIALOG, pParent) { m_nIndex = 0; m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CFlyRgnDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CFlyRgnDlg, CDialogEx) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_TIMER() ON_WM_ERASEBKGND() ON_WM_NCPAINT() END_MESSAGE_MAP() // CFlyRgnDlg message handlers BOOL CFlyRgnDlg::OnInitDialog() { CDialogEx::OnInitDialog(); int i = 0; CString str; while (i < FLY_CNT) { //加载多张动画图片并且每张图片根据透明色区域生成一个区域 str.Format(_TEXT("./flys/%03d.bmp"), i + 1); m_dc[i].LoadBitmapW(str); m_dc[i].BitRgn(m_rgn[i], TRANSCOLOR); i++; } ModifyStyle(GetStyle(), 0);//去掉标题栏和边框 ModifyStyleEx(GetExStyle(), WS_EX_TOOLWINDOW);//不在任务栏显示 //创建一个屏幕随机坐标 int cx = GetSystemMetrics(SM_CXSCREEN); int cy = GetSystemMetrics(SM_CYSCREEN); srand(time(NULL)); m_pos.x = rand() % (cx - m_dc[0].Width()); m_pos.y = rand() % (cy - m_dc[0].Height()); CMemoryDC &mdc = m_dc[m_nIndex];//设置窗口位置并置顶 SetWindowPos(&wndTopMost, m_pos.x, m_pos.y, mdc.Width(), mdc.Height(), 0); CRgn rgn; //选择一个帧区域复制后设置到窗口 rgn.CreateRectRgn(0, 0, 0, 0); rgn.CopyRgn(&m_rgn[m_nIndex]); SetWindowRgn(rgn, TRUE); //启动定时器 SetTimer(0, 64, NULL); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CFlyRgnDlg::OnPaint() { CPaintDC dc(this); OnDraw(&dc); } // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CFlyRgnDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CFlyRgnDlg::OnTimer(UINT_PTR nIDEvent) { // TODO: Add your message handler code here and/or call default /* CmemoryDC &mdc = m_dc[m_nIndex]; MoveWindow(m_pos.x, m_pos.y, mdc.GetWidth(), mdc.GetHeight()); CRgn rgn; rgn.CreateRectRgn(0, 0, 0, 0); rgn.CopyRgn(&m_rgn[m_nIndex]); SetWindowRgn(rgn, TRUE); CClientDC dc(this); mdc.BitTrans(0, 0, mdc.GetWidth(), mdc.GetHeight(), &dc, 0, 0, SRCCOPY); static int cx = 5, cy = 5; m_pos.Offset(cx, cy); if (m_pos.x + mdc.GetWidth() > GetSystemMetrics(SM_CXSCREEN) || m_pos.x < 0) cx *= -1; if (m_pos.y + mdc.GetHeight() > GetSystemMetrics(SM_CYSCREEN) || m_pos.y < 0) cy *= -1; if (++m_nIndex >= FLY_CNT) m_nIndex = 0;*/ CClientDC dc(this); Invalidate(FALSE); CDialogEx::OnTimer(nIDEvent); } void CFlyRgnDlg::OnDraw(CDC *pDC) { CMemoryDC &mdc = m_dc[m_nIndex]; MoveWindow(m_pos.x, m_pos.y, mdc.Width(), mdc.Height()); CRgn rgn; rgn.CreateRectRgn(0, 0, 0, 0); rgn.CopyRgn(&m_rgn[m_nIndex]); SetWindowRgn(rgn, TRUE); mdc.BitTrans(0, 0, mdc.Width(), mdc.Height(), pDC, 0, 0, TRANSCOLOR); static int cx = 5, cy = 5; m_pos.Offset(cx, cy); if (m_pos.x + mdc.Width() > GetSystemMetrics(SM_CXSCREEN) || m_pos.x < 0) cx *= -1; if (m_pos.y + mdc.Height() > GetSystemMetrics(SM_CYSCREEN) || m_pos.y < 0) cy *= -1; if (++m_nIndex >= FLY_CNT) m_nIndex = 0; } BOOL CFlyRgnDlg::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default return TRUE; // return CDialogEx::OnEraseBkgnd(pDC); } void CFlyRgnDlg::OnNcPaint() { // TODO: Add your message handler code here // Do not call CDialogEx::OnNcPaint() for painting messages } ``` ![失败的效果](https://img-ask.csdn.net/upload/201708/16/1502854706_811662.png)
下面的代码怎么实现双缓存去闪
// 画图View.cpp : implementation of the CMyView class // #include "stdafx.h" #include "画图.h" #include "画图Doc.h" #include "画图View.h" #include "SettingDlg.h" #include<vector> #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMyView IMPLEMENT_DYNCREATE(CMyView, CView) BEGIN_MESSAGE_MAP(CMyView, CView) //{{AFX_MSG_MAP(CMyView) ON_COMMAND(IDM_LINE, OnLine) ON_COMMAND(IDM_RECTANGLE, OnRectangle) ON_COMMAND(IDM_Circle, OnCircle) ON_COMMAND(IDM_Random_Line, OnRandomLine) ON_COMMAND(IDM_POLYGON, OnPolygon) ON_WM_LBUTTONUP() ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_RBUTTONDOWN() ON_WM_RBUTTONUP() ON_COMMAND(IDM_SET_LINE_STYLE_WIDTH, OnSetLineStyleWidth) ON_COMMAND(IDM_SET_COLOR, OnSetColor) //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMyView construction/destruction CMyView::CMyView() { // TODO: add construction code here m_nDrawType=0; m_ptOrigin=0; m_nLineStyle=0; m_nLineWidth=1; m_ncolor=RGB(255,0,0); m_dcMetaFile.Create(); no1=0; no2=0; no3=0; no4=0; no5=0; k=0; } CMyView::~CMyView() { } BOOL CMyView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CMyView drawing void CMyView::OnDraw(CDC* pDC) { CMyDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CClientDC dc(this); CPen pen(m_nLineStyle,m_nLineWidth,m_color); CPen* pOldPen = pDC->SelectObject(&pen); CPoint point1,point2; int temp=k; //vector<CPoint>::const_iterator i=v.begin(); if(no1 ||no2 ||no3 ||no4|| no5){ switch(m_nDrawType) { case 1: pDC->MoveTo(pDoc->head); point1.x=pDoc->head.x+5; point1.y=pDoc->head.y+5; point2.x=pDoc->head.x-5; point2.y=pDoc->head.y-5; pDC->Ellipse(CRect(point1,point2)); pDC->LineTo(pDoc->tail); point1.x=pDoc->tail.x+5; point1.y=pDoc->tail.y+5; point2.x=pDoc->tail.x-5; point2.y=pDoc->tail.y-5; pDC->Ellipse(CRect(point1,point2)); break; case 2: point1.x=pDoc->m_Rect.left+5; point1.y=pDoc->m_Rect.top+5; point2.x=point1.x-10; point2.y=point1.y-10; pDC->Ellipse(CRect(point1,point2)); point1.x=pDoc->m_Rect.right+5; point2.x=point1.x-10; pDC->Ellipse(CRect(point1,point2)); point1.x=pDoc->m_Rect.left+5; point1.y=pDoc->m_Rect.bottom+5; point2.x=point1.x-10; point2.y=point1.y-10; pDC->Ellipse(CRect(point1,point2)); point1.x=pDoc->m_Rect.right+5; point2.x=point1.x-10; pDC->Ellipse(CRect(point1,point2)); pDC->Rectangle(pDoc->m_Rect); break; case 3: pDC->Ellipse(pDoc->m_Rect); break; case 4: for(temp=0;temp<k-1;temp++) { pDC->MoveTo(pDoc->pointduo[temp]); point1.x=pDoc->pointduo[temp].x+5; point1.y=pDoc->pointduo[temp].y+5; point2.x=pDoc->pointduo[temp].x-5; point2.y=pDoc->pointduo[temp].y-5; pDC->Ellipse(CRect(point1,point2)); pDC->LineTo(pDoc->pointduo[temp+1]); point1.x=pDoc->pointduo[temp+1].x+5; point1.y=pDoc->pointduo[temp+1].y+5; point2.x=pDoc->pointduo[temp+1].x-5; point2.y=pDoc->pointduo[temp+1].y-5; pDC->Ellipse(CRect(point1,point2)); } pDC->MoveTo(pDoc->pointduo[temp]); point1.x=pDoc->pointduo[temp].x+5; point1.y=pDoc->pointduo[temp].y+5; point2.x=pDoc->pointduo[temp].x-5; point2.y=pDoc->pointduo[temp].y-5; pDC->Ellipse(CRect(point1,point2)); pDC->LineTo(pDoc->tail); point1.x=pDoc->tail.x+5; point1.y=pDoc->tail.y+5; point2.x=pDoc->tail.x-5; point2.y=pDoc->tail.y-5; pDC->Ellipse(CRect(point1,point2)); break; case 5: for(temp=0;temp<k-1;temp++) { pDC->MoveTo(pDoc->pointp[temp]); point1.x=pDoc->pointp[temp].x+5; point1.y=pDoc->pointp[temp].y+5; point2.x=pDoc->pointp[temp].x-5; point2.y=pDoc->pointp[temp].y-5; pDC->Ellipse(CRect(point1,point2)); pDC->LineTo(pDoc->pointp[temp+1]); point1.x=pDoc->pointp[temp+1].x+5; point1.y=pDoc->pointp[temp+1].y+5; point2.x=pDoc->pointp[temp+1].x-5; point2.y=pDoc->pointp[temp+1].y-5; pDC->Ellipse(CRect(point1,point2)); } pDC->MoveTo(pDoc->pointp[temp]); point1.x=pDoc->pointp[temp].x+5; point1.y=pDoc->pointp[temp].y+5; point2.x=pDoc->pointp[temp].x-5; point2.y=pDoc->pointp[temp].y-5; pDC->Ellipse(CRect(point1,point2)); pDC->LineTo(pDoc->tail); point1.x=pDoc->tail.x+5; point1.y=pDoc->tail.y+5; point2.x=pDoc->tail.x-5; point2.y=pDoc->tail.y-5; pDC->Ellipse(CRect(point1,point2)); pDC->MoveTo(pDoc->tail); point1.x=pDoc->tail.x+5; point1.y=pDoc->tail.y+5; point2.x=pDoc->tail.x-5; point2.y=pDoc->tail.y-5; pDC->Ellipse(CRect(point1,point2)); pDC->LineTo(pDoc->pointp[0]); point1.x=pDoc->pointp[0].x+5; point1.y=pDoc->pointp[0].y+5; point2.x=pDoc->pointp[0].x-5; point2.y=pDoc->pointp[0].y-5; pDC->Ellipse(CRect(point1,point2)); } } } ///////////////////////////////////////////////////////////////////////////// // CMyView printing BOOL CMyView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CMyView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add extra initialization before printing } void CMyView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add cleanup after printing } ///////////////////////////////////////////////////////////////////////////// // CMyView diagnostics #ifdef _DEBUG void CMyView::AssertValid() const { CView::AssertValid(); } void CMyView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CMyDoc* CMyView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyDoc))); return (CMyDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CMyView message handlers //DEL void CMyView::OnUpdateLine(CCmdUI* pCmdUI) //DEL { //DEL // TODO: Add your command update UI handler code here //DEL //DEL } void CMyView::OnLine() { // TODO: Add your command handler code here m_nDrawType=1; } void CMyView::OnRectangle() { // TODO: Add your command handler code here m_nDrawType=2; } void CMyView::OnCircle() { // TODO: Add your command handler code here m_nDrawType=3; } void CMyView::OnRandomLine() { // TODO: Add your command handler code here m_nDrawType=4; } void CMyView::OnPolygon() { // TODO: Add your command handler code here m_nDrawType=5; } void CMyView::OnLButtonUp(UINT nFlags, CPoint point) { CView::OnLButtonUp(nFlags, point); } void CMyView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CClientDC dc(this); CPoint point1,point2; m_ptOrigin=point; CMyDoc* pDoc = GetDocument(); if(m_nDrawType==4) { pDoc->pointduo[k]=point; k++; } if(m_nDrawType==5) { pDoc->pointp[k]=point; k++; } if(no1||no2||no3) { switch(m_nDrawType) { case 1:if(no1==1)no1=0;break; case 2:if(no2==1)no2=0;break; case 3:if(no3==1)no3=0;break; } } else if(m_nDrawType!=0) { if(m_nDrawType!=3) { CPen pen(0,1,m_color); CPen* pOldPen = dc.SelectObject(&pen); point1.x=point.x+5; point1.y=point.y+5; point2.x=point.x-5; point2.y=point.y-5; dc.Ellipse(CRect(point1,point2)); } switch(m_nDrawType) { case 1:no1=1; break; case 2:no2=1; break; case 3:no3=1; break; case 4:no4=1; break; case 5:no5=1; break; } } CView::OnLButtonDown(nFlags, point); } void CMyView::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CPoint m_ptEnd=point; CPoint point1,point2,point3,point4; CMyDoc* pDoc = GetDocument(); CClientDC dc(this); switch(m_nDrawType) { case 1: pDoc->head=m_ptOrigin; pDoc->tail=m_ptEnd; if(no1) Invalidate(); break; case 2:case 3: pDoc->m_Rect.left=m_ptOrigin.x; pDoc->m_Rect.top=m_ptOrigin.y; pDoc->m_Rect.right=m_ptEnd.x; pDoc->m_Rect.bottom=m_ptEnd.y; if(no2 || no3) Invalidate(); case 4:case 5: pDoc->tail=m_ptEnd; if(no5 || no4) Invalidate(); break; } CView::OnMouseMove(nFlags, point); } void CMyView::OnRButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CView::OnRButtonDown(nFlags, point); } void CMyView::OnRButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if(m_nDrawType==4) { no4=0; k=0; } if(m_nDrawType==5) { no5=0; k=0; } CView::OnRButtonUp(nFlags, point); } void CMyView::OnSetLineStyleWidth() { // TODO: Add your command handler code here CSettingDlg dlg; //dlg.DoModal(); dlg.m_nLineWidth=m_nLineWidth; dlg.m_nLineStyle=m_nLineStyle; if(IDOK==dlg.DoModal()) { m_nLineWidth=dlg.m_nLineWidth ; m_nLineStyle=dlg.m_nLineStyle ; } } void CMyView::OnSetColor() { // TODO: Add your command handler code here CColorDialog dlg; dlg.m_cc.Flags |=CC_RGBINIT | CC_FULLOPEN; dlg.m_cc.rgbResult=m_color; if(IDOK==dlg.DoModal()) { m_color=dlg.m_cc.rgbResult; } }
在中国程序员是青春饭吗?
今年,我也32了 ,为了不给大家误导,咨询了猎头、圈内好友,以及年过35岁的几位老程序员……舍了老脸去揭人家伤疤……希望能给大家以帮助,记得帮我点赞哦。 目录: 你以为的人生 一次又一次的伤害 猎头界的真相 如何应对互联网行业的「中年危机」 一、你以为的人生 刚入行时,拿着傲人的工资,想着好好干,以为我们的人生是这样的: 等真到了那一天,你会发现,你的人生很可能是这样的: ...
《MySQL 性能优化》之理解 MySQL 体系结构
本文介绍 MySQL 的体系结构,包括物理结构、逻辑结构以及插件式存储引擎。
程序员请照顾好自己,周末病魔差点一套带走我。
程序员在一个周末的时间,得了重病,差点当场去世,还好及时挽救回来了。
Python+OpenCV实时图像处理
目录 1、导入库文件 2、设计GUI 3、调用摄像头 4、实时图像处理 4.1、阈值二值化 4.2、边缘检测 4.3、轮廓检测 4.4、高斯滤波 4.5、色彩转换 4.6、调节对比度 5、退出系统 初学OpenCV图像处理的小伙伴肯定对什么高斯函数、滤波处理、阈值二值化等特性非常头疼,这里给各位分享一个小项目,可通过摄像头实时动态查看各类图像处理的特点,也可对各位调参、测试...
2020年一线城市程序员工资大调查
人才需求 一线城市共发布岗位38115个,招聘120827人。 其中 beijing 22805 guangzhou 25081 shanghai 39614 shenzhen 33327 工资分布 2020年中国一线城市程序员的平均工资为16285元,工资中位数为14583元,其中95%的人的工资位于5000到20000元之间。 和往年数据比较: yea...
为什么猝死的都是程序员,基本上不见产品经理猝死呢?
相信大家时不时听到程序员猝死的消息,但是基本上听不到产品经理猝死的消息,这是为什么呢? 我们先百度搜一下:程序员猝死,出现将近700多万条搜索结果: 搜索一下:产品经理猝死,只有400万条的搜索结果,从搜索结果数量上来看,程序员猝死的搜索结果就比产品经理猝死的搜索结果高了一倍,而且从下图可以看到,首页里面的五条搜索结果,其实只有两条才是符合条件。 所以程序员猝死的概率真的比产品经理大,并不是错...
害怕面试被问HashMap?这一篇就搞定了!
声明:本文以jdk1.8为主! 搞定HashMap 作为一个Java从业者,面试的时候肯定会被问到过HashMap,因为对于HashMap来说,可以说是Java集合中的精髓了,如果你觉得自己对它掌握的还不够好,我想今天这篇文章会非常适合你,至少,看了今天这篇文章,以后不怕面试被问HashMap了 其实在我学习HashMap的过程中,我个人觉得HashMap还是挺复杂的,如果真的想把它搞得明明白...
毕业5年,我问遍了身边的大佬,总结了他们的学习方法
我问了身边10个大佬,总结了他们的学习方法,原来成功都是有迹可循的。
python爬取百部电影数据,我分析出了一个残酷的真相
2019年就这么匆匆过去了,就在前几天国家电影局发布了2019年中国电影市场数据,数据显示去年总票房为642.66亿元,同比增长5.4%;国产电影总票房411.75亿元,同比增长8.65%,市场占比 64.07%;城市院线观影人次17.27亿,同比增长0.64%。 看上去似乎是一片大好对不对?不过作为一名严谨求实的数据分析师,我从官方数据中看出了一点端倪:国产票房增幅都已经高达8.65%了,为什...
推荐10个堪称神器的学习网站
每天都会收到很多读者的私信,问我:“二哥,有什么推荐的学习网站吗?最近很浮躁,手头的一些网站都看烦了,想看看二哥这里有什么新鲜货。” 今天一早做了个恶梦,梦到被老板辞退了。虽然说在我们公司,只有我辞退老板的份,没有老板辞退我这一说,但是还是被吓得 4 点多都起来了。(主要是因为我掌握着公司所有的核心源码,哈哈哈) 既然 4 点多起来,就得好好利用起来。于是我就挑选了 10 个堪称神器的学习网站,推...
这些软件太强了,Windows必装!尤其程序员!
Windows可谓是大多数人的生产力工具,集娱乐办公于一体,虽然在程序员这个群体中都说苹果是信仰,但是大部分不都是从Windows过来的,而且现在依然有很多的程序员用Windows。 所以,今天我就把我私藏的Windows必装的软件分享给大家,如果有一个你没有用过甚至没有听过,那你就赚了????,这可都是提升你幸福感的高效率生产力工具哦! 走起!???? NO、1 ScreenToGif 屏幕,摄像头和白板...
阿里面试,面试官没想到一个ArrayList,我都能跟他扯半小时
我是真的没想到,面试官会这样问我ArrayList。
曾经优秀的人,怎么就突然不优秀了。
职场上有很多辛酸事,很多合伙人出局的故事,很多技术骨干被裁员的故事。说来模板都类似,曾经是名校毕业,曾经是优秀员工,曾经被领导表扬,曾经业绩突出,然而突然有一天,因为种种原因,被裁员了,...
C语言荣获2019年度最佳编程语言
关注、星标公众号,不错过精彩内容作者:黄工公众号:strongerHuang近日,TIOBE官方发布了2020年1月编程语言排行榜单。我在前面给过一篇文章《2019年11月C语言接近Ja...
大学四年因为知道了这32个网站,我成了别人眼中的大神!
依稀记得,毕业那天,我们导员发给我毕业证的时候对我说“你可是咱们系的风云人物啊”,哎呀,别提当时多开心啦????,嗯,我们导员是所有导员中最帅的一个,真的???? 不过,导员说的是实话,很多人都叫我大神的,为啥,因为我知道这32个网站啊,你说强不强????,这次是绝对的干货,看好啦,走起来! PS:每个网站都是学计算机混互联网必须知道的,真的牛杯,我就不过多介绍了,大家自行探索,觉得没用的,尽管留言吐槽吧???? 社...
良心推荐,我珍藏的一些Chrome插件
上次搬家的时候,发了一个朋友圈,附带的照片中不小心暴露了自己的 Chrome 浏览器插件之多,于是就有小伙伴评论说分享一下我觉得还不错的浏览器插件。 我下面就把我日常工作和学习中经常用到的一些 Chrome 浏览器插件分享给大家,随便一个都能提高你的“生活品质”和工作效率。 Markdown Here Markdown Here 可以让你更愉快的写邮件,由于支持 Markdown 直接转电子邮...
看完这篇HTTP,跟面试官扯皮就没问题了
我是一名程序员,我的主要编程语言是 Java,我更是一名 Web 开发人员,所以我必须要了解 HTTP,所以本篇文章就来带你从 HTTP 入门到进阶,看完让你有一种恍然大悟、醍醐灌顶的感觉。 最初在有网络之前,我们的电脑都是单机的,单机系统是孤立的,我还记得 05 年前那会儿家里有个电脑,想打电脑游戏还得两个人在一个电脑上玩儿,及其不方便。我就想为什么家里人不让上网,我的同学 xxx 家里有网,每...
史上最全的IDEA快捷键总结
现在Idea成了主流开发工具,这篇博客对其使用的快捷键做了总结,希望对大家的开发工作有所帮助。
阿里程序员写了一个新手都写不出的低级bug,被骂惨了。
这种新手都不会范的错,居然被一个工作好几年的小伙子写出来,差点被当场开除了。
谁是华为扫地僧?
是的,华为也有扫地僧!2020年2月11-12日,“养在深闺人不知”的华为2012实验室扫地僧们,将在华为开发者大会2020(Cloud)上,和大家见面。到时,你可以和扫地僧们,吃一个洋...
AI 没让人类失业,搞 AI 的人先失业了
最近和几个 AI 领域的大佬闲聊 根据他们讲的消息和段子 改编出下面这个故事 如有雷同 都是巧合 1. 老王创业失败,被限制高消费 “这里写我跑路的消息实在太夸张了。” 王葱葱哼笑一下,把消息分享给群里。 阿杰也看了消息,笑了笑。在座几位也都笑了。 王葱葱是个有名的人物,21岁那年以全额奖学金进入 KMU 攻读人工智能博士,累计发表论文 40 余篇,个人技术博客更是成为深度学习领域内风向标。 ...
2020年,冯唐49岁:我给20、30岁IT职场年轻人的建议
点击“技术领导力”关注∆每天早上8:30推送 作者|Mr.K 编辑| Emma 来源|技术领导力(ID:jishulingdaoli) 前天的推文《冯唐:职场人35岁以后,方法论比经验重要》,收到了不少读者的反馈,觉得挺受启发。其实,冯唐写了不少关于职场方面的文章,都挺不错的。可惜大家只记住了“春风十里不如你”、“如何避免成为油腻腻的中年人”等不那么正经的文章。 本文整理了冯...
一份王者荣耀的英雄数据报告
咪哥杂谈本篇阅读时间约为 6 分钟。1前言前一阵写了关于王者的一些系列文章,从数据的获取到数据清洗,数据落地,都是为了本篇的铺垫。今天来实现一下,看看不同维度得到的结论。2环境准备本次实...
作为一名大学生,如何在B站上快乐的学习?
B站是个宝,谁用谁知道???? 作为一名大学生,你必须掌握的一项能力就是自学能力,很多看起来很牛X的人,你可以了解下,人家私底下一定是花大量的时间自学的,你可能会说,我也想学习啊,可是嘞,该学习啥嘞,不怕告诉你,互联网时代,最不缺的就是学习资源,最宝贵的是啥? 你可能会说是时间,不,不是时间,而是你的注意力,懂了吧! 那么,你说学习资源多,我咋不知道,那今天我就告诉你一个你必须知道的学习的地方,人称...
那些年,我们信了课本里的那些鬼话
教材永远都是有错误的,从小学到大学,我们不断的学习了很多错误知识。 斑羚飞渡 在我们学习的很多小学课文里,有很多是错误文章,或者说是假课文。像《斑羚飞渡》: 随着镰刀头羊的那声吼叫,整个斑羚群迅速分成两拨,老年斑羚为一拨,年轻斑羚为一拨。 就在这时,我看见,从那拨老斑羚里走出一只公斑羚来。公斑羚朝那拨年轻斑羚示意性地咩了一声,一只半大的斑羚应声走了出来。一老一少走到伤心崖,后退了几步,突...
一个程序在计算机中是如何运行的?超级干货!!!
强烈声明:本文很干,请自备茶水!???? 开门见山,咱不说废话! 你有没有想过,你写的程序,是如何在计算机中运行的吗?比如我们搞Java的,肯定写过这段代码 public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } ...
【蘑菇街技术部年会】程序员与女神共舞,鼻血再次没止住。(文末内推)
蘑菇街技术部的年会,别开生面,一样全是美女。
那个在阿里养猪的工程师,5年了……
简介: 在阿里,走过1825天,没有趴下,依旧斗志满满,被称为“五年陈”。他们会被授予一枚戒指,过程就叫做“授戒仪式”。今天,咱们听听阿里的那些“五年陈”们的故事。 下一个五年,猪圈见! 我就是那个在养猪场里敲代码的工程师,一年多前我和20位工程师去了四川的猪场,出发前总架构师慷慨激昂的说:同学们,中国的养猪产业将因为我们而改变。但到了猪场,发现根本不是那么回事:要个WIFI,没有;...
为什么程序猿都不愿意去外包?
分享外包的组织架构,盈利模式,亲身经历,以及根据一些外包朋友的反馈,写了这篇文章 ,希望对正在找工作的老铁有所帮助
Java校招入职华为,半年后我跑路了
何来 我,一个双非本科弟弟,有幸在 19 届的秋招中得到前东家华为(以下简称 hw)的赏识,当时秋招签订就业协议,说是入了某 java bg,之后一系列组织架构调整原因等等让人无法理解的神操作,最终毕业前夕,被通知调往其他 bg 做嵌入式开发(纯 C 语言)。 由于已至于校招末尾,之前拿到的其他 offer 又无法再收回,一时感到无力回天,只得默默接受。 毕业后,直接入职开始了嵌入式苦旅,由于从未...
世界上有哪些代码量很少,但很牛逼很经典的算法或项目案例?
点击上方蓝字设为星标下面开始今天的学习~今天分享四个代码量很少,但很牛逼很经典的算法或项目案例。1、no code 项目地址:https://github.com/kelseyhight...
立即提问