请问在handleMessage里能不能使用Canvas画图

本文探讨了使用Handler接收消息并在Android环境中根据不同消息类型绘制图形的方法。重点介绍了如何通过Canvas和Paint对象来实现画线和画圆的功能。

设计想法:在接收到主机发来的数据后,交给handler,handler根据消息不同画图。但是貌似根本画不出来,不知道哪位知道原因?
private Handler myHandler = new Handler()
        {
                // 2.重写消息处理函数
                public void handleMessage(Message msg)
                {
                        switch (msg.what)
                        {
                                // 判断发送的消息
                                case 1://画线
                                {
                                        Canvas canvas = new Canvas();
                                        canvas.drawColor(Color.WHITE);
                                        
                                        Paint paint = new Paint();
                                        paint.setColor(Color.BLUE);

                                        canvas.drawLine(300, 400, 200, 200, paint);
                                        break;
                                }
                                case 2://画圆
                                {
                                        Canvas canvas = new Canvas();
                                        canvas.drawColor(Color.WHITE);
                                        
                                        Paint paint = new Paint();
                                        paint.setColor(Color.BLUE);

                                        canvas.drawCircle(50, 100, 50, mPaint);
                                        break;
                                }

                        }
                        super.handleMessage(msg);
                }
        };
public class TelescopeView extends View { // 放大镜的半径 private static final int RADIUS = 80; // 放大倍数 private static final int FACTOR = 3; private final Matrix matrix = new Matrix(); private Bitmap bitmap; private ShapeDrawable shapeDrawable; public TelescopeView(Context context) { super(context); init(); } public TelescopeView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } public TelescopeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { setLayerType(LAYER_TYPE_SOFTWARE, null); } private Handler handler = new Handler(Looper.getMainLooper()); private Runnable hideRunnable = new Runnable() { @Override public void run() { if (shapeDrawable != null) { shapeDrawable.setBounds(0, 0, 0, 0); // 隐藏放大镜 invalidate(); } } }; @Override protected void onDraw(@NonNull Canvas canvas) { super.onDraw(canvas); if (bitmap == null) { // 从资源中加载一张图片,并生成新的Bitmap Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.telescope_test_img); bitmap = Bitmap.createScaledBitmap(bmp, getWidth(), getHeight(), true); // 创建一个圆形的ShapeDrawable,并使用一个经过缩放的位图作为其填充着色器(BitmapShader) BitmapShader shader = new BitmapShader(Bitmap.createScaledBitmap(bitmap, getWidth() * FACTOR, bitmap.getHeight() * FACTOR, true), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); shapeDrawable = new ShapeDrawable(new OvalShape()); shapeDrawable.getPaint().setShader(shader); shapeDrawable.setBounds(0, 0, RADIUS * 2, RADIUS *2 ); } // 绘制原始图片 canvas.drawBitmap(bitmap, 0, 0, null); // 绘制放大后的图片 shapeDrawable.draw(canvas); } @Override public boolean onTouchEvent(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: // 移除之前可能存在的延迟任务,防止重复执行 handler.removeCallbacks(hideRunnable); // 控制 Shader(如 BitmapShader)在 ShapeDrawable 上的绘制位置的 // 放大镜核心原理 // 画图区域:以手指的位置(X,Y)为圆心画半径为RADIUS的圆; // (X,Y) -> (3X,3Y) 偏移半径的长度 matrix.setTranslate(RADIUS - x * FACTOR, RADIUS - y * FACTOR); shapeDrawable.getPaint().getShader().setLocalMatrix(matrix); // 绘制区域 shapeDrawable.setBounds(x - RADIUS, y - RADIUS, x + RADIUS , y + RADIUS); break; case MotionEvent.ACTION_UP: // 延迟 3 秒后隐藏放大镜 handler.postDelayed(hideRunnable, 3000); break; } invalidate(); return true; } } 分析代码的问题
最新发布
09-08
### 解决 `handleMessage` 中调用 `setAdapter(adapter)` 后数据无法显示的问题 在 Android 开发中,当通过 `Handler` 的 `handleMessage` 方法更新 UI 并设置适配器时,数据可能无法正确显示。以下是可能导致此问题的原因及解决方法。 #### 1. 数据源未及时更新 如果在 `handleMessage` 方法中直接调用 `setAdapter(adapter)`,但数据源尚未完成更新,则适配器会绑定一个空的数据集[^1]。需要确保数据源已完全初始化后再创建适配器。 ```java // 在 handleMessage 方法中更新数据源 List<String> dataList = new ArrayList<>(); dataList.add("Item 1"); dataList.add("Item 2"); // 创建适配器并绑定数据源 ArrayAdapter<String> adapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, dataList); listView.setAdapter(adapter); ``` #### 2. 未通知适配器数据变化 即使数据源已更新,若未调用 `notifyDataSetChanged()` 方法通知适配器数据已更改,则视图不会刷新[^2]。需在更新数据后显式调用该方法。 ```java // 更新数据源 dataList.add("Item 3"); // 通知适配器数据已更改 adapter.notifyDataSetChanged(); ``` #### 3. 线程问题 `handleMessage` 方法运行在主线程中,但如果数据的获取或解析发生在后台线程中,则可能导致数据未准备好就调用了 `setAdapter(adapter)`[^4]。应确保数据准备完成后才进行 UI 更新。 ```java new Thread(new Runnable() { @Override public void run() { // 模拟网络请求或耗时操作 final List<String> newsList = getNewsInfo(); // 切换到主线程更新 UI handler.post(new Runnable() { @Override public void run() { NewsAdapter adapter = new NewsAdapter(context, R.layout.listview_item, newsList); listView.setAdapter(adapter); } }); } }).start(); ``` #### 4. 视图未正确初始化 如果 `ListView` 或其他视图组件未正确初始化,则即使适配器已设置,数据也无法显示[^4]。需确保视图已在 `onCreate` 或 `onViewCreated` 中正确绑定。 ```java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listView = findViewById(R.id.list_view); if (listView == null) { throw new IllegalStateException("ListView not initialized"); } // 初始化适配器 ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new ArrayList<>()); listView.setAdapter(adapter); } ``` #### 5. 自定义适配器实现错误 如果使用了自定义适配器,可能由于 `getView()` 方法实现不当导致数据无法正确显示[^3]。需确保每个视图项都能正确返回。 ```java public class CustomAdapter extends BaseAdapter { private Context context; private List<String> dataList; public CustomAdapter(Context context, List<String> dataList) { this.context = context; this.dataList = dataList; } @Override public int getCount() { return dataList.size(); // 返回数据项数量 } @Override public Object getItem(int position) { return dataList.get(position); // 返回指定位置的数据项 } @Override public long getItemId(int position) { return position; // 返回唯一标识符 } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.item_custom, parent, false); } TextView textView = convertView.findViewById(R.id.text_view); textView.setText(dataList.get(position)); return convertView; } } ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值