创建全新的视图将满足我们独特的UI需求。

本文介绍在指南针开发中会用到的罗盘的界面UI,通过继承View类实现的自定义视图,以此来深刻了解自定义视图。

实现效果图:


源代码:

布局文件activity_main(其中CompassView继承View类):

<FrameLayout 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"    tools:context=".MainActivity" >    <com.professionalandroiddemo6.CompassView        android:id="@+id/compassView"        android:layout_width="match_parent"        android:layout_height="match_parent" /></FrameLayout>

res/values文件夹下的:

string.xml:

<?xml version="1.0" encoding="utf-8"?><resources>    <string name="app_name">ProfessionalAndroidDemo6</string>    <string name="action_settings" font = "14sp">Settings</string>    <string name="hello_world">Hello world!</string><string name="north">N</string><string name="east">E</string><string name="south">S</string><string name="west">W</string></resources>

colors.xml:

<?xml version="1.0" encoding="utf-8"?><resources>    <color name="background">#F555</color>    <color name="maker">#AFFF</color>    <color name="text">#AFFF</color>    </resources>
代码文件;

MainActivity:

package com.professionalandroiddemo6;import android.app.Activity;import android.os.Bundle;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}}

CompassView:

package com.professionalandroiddemo6;/** * 自定义视图--指南针界面 */import android.content.Context;import android.content.res.Resources;import android.graphics.Canvas;import android.graphics.Paint;import android.util.AttributeSet;import android.view.View;import android.view.accessibility.AccessibilityEvent;public class CompassView extends View {private Paint markerPaint;private Paint circlePaint;private Paint textPaint;private String north, south, east, west;private int textHeight;private String dirString;private float bearing;public void setBearing(float _bearing) {bearing = _bearing;sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);}public float getBearing() {return bearing;}public CompassView(Context context) {super(context);initCompassView();}public CompassView(Context context, AttributeSet attrs) {super(context, attrs);initCompassView();}public CompassView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initCompassView();}private void initCompassView() {setFocusable(true);Resources resources = this.getResources();circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);circlePaint.setColor(resources.getColor(R.color.background));circlePaint.setStrokeWidth(1);circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);north = resources.getString(R.string.north);south = resources.getString(R.string.south);east = resources.getString(R.string.east);west = resources.getString(R.string.west);textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);textPaint.setColor(resources.getColor(R.color.text));textPaint.setTextSize((float) 30);// 此处设置将要显示的字体的大小。textHeight = (int) textPaint.measureText("yY");markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);markerPaint.setColor(resources.getColor(R.color.maker));}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// 罗盘是一个填充尽可能多的空间的圆,通过设置最短的边界、高度或者宽度来设置测量的尺寸。int measuredWidth = measure(widthMeasureSpec);int measuredHeight = measure(heightMeasureSpec);int d = Math.min(measuredWidth, measuredHeight);setMeasuredDimension(d, d);}private int measure(int measureSpec) {int result = 0;// 对测量说明进行解码int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);if (specMode == MeasureSpec.UNSPECIFIED) {// 如果没有指定界限了,则默认返回值为200result = 200;} else {// 由于你希望填充可用的空间,所以总是返回整个可用的边界result = specSize;}return result;}@Overrideprotected void onDraw(Canvas canvas) {// 找到控件的中心,并将最小边的长度作为罗盘的半径存储起来。int mMeasuredWidth = getMeasuredWidth();int mMeasuredHeight = getMeasuredHeight();int px = mMeasuredWidth / 2;int py = mMeasuredHeight / 2;int radius = Math.min(px, py);// 使用drawCircle方法画出罗盘字符的边界,并为其北京着色。canvas.drawCircle(px, py, radius, circlePaint);canvas.save();canvas.rotate(-bearing, px, py);// 剩下要做的就只有绘制标记了。把画布旋转一圈,并且每15度画一个标记,每45度画一个方向的缩写。int textWidth = (int) textPaint.measureText("W");int cardinalX = px - textWidth / 2;int cardinalY = py - radius + textHeight;// 每15度绘制一个标记,每45度绘制一个文本for (int i = 0; i < 24; i++) {canvas.drawLine(px, py - radius, px, py - radius + 20, markerPaint);canvas.save();canvas.translate(0, textHeight);// 绘制基本方位if (i % 6 == 0) {switch (i) {case 0: {dirString = north;int arrowY = 2 * textHeight;canvas.drawLine(px, arrowY, px - 5, 5 * textHeight,markerPaint);canvas.drawLine(px, arrowY, px + 5, 5 * textHeight,markerPaint);}break;case 6:dirString = east;break;case 12:dirString = south;break;case 18:dirString = west;break;}canvas.drawText(dirString, cardinalX, cardinalY, textPaint);} else if (i % 3 == 0) {// 每45度绘制文本String angle = String.valueOf(i * 15);float angleTextWidth = textPaint.measureText(angle);int angleTextX = (int) (px - angleTextWidth / 2);int angleTextY = py - radius + textHeight;canvas.drawText(angle, angleTextX, angleTextY, textPaint);}canvas.restore();canvas.rotate(15, px, py);}canvas.restore();}@Overridepublic boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {super.dispatchPopulateAccessibilityEvent(event);if (isShown()) {String bearingStr = String.valueOf(bearing);if (bearingStr.length() > AccessibilityEvent.MAX_TEXT_LENGTH)bearingStr = bearingStr.substring(0,AccessibilityEvent.MAX_TEXT_LENGTH);event.getText().add(bearingStr);return true;}return false;}}

源代码下载:

点击下载源码

更多相关文章

  1. Android(安卓)opengl es 2.0怎么学习
  2. Android通信方式(一)————WebView
  3. Android自定义ViewPager(一)——自定义Scroller模拟动画过程
  4. 【笔记】Android上ROS开发——android_core创建一个android应用
  5. 【UI交互效果】android UI效果二: 给选中的图片加边框
  6. view的几种布局方式及实践
  7. android 图片的拉伸方式(scaleType)
  8. [Android进阶]Android(安卓)开发最佳实践
  9. Android使用Canvas绘制圆形进度条效果

随机推荐

  1. activity的生命周期——第一行代码阅读笔
  2. Android(安卓)双缓冲技术
  3. Android事件传递机制(更加深入的了解事件
  4. Android(安卓)LitePal的简单使用
  5. 如何正确的在 Android(安卓)上使用协程 ?
  6. Android利用mediacodec进行视频H264编码
  7. 谷歌Android(安卓)UI设计技巧
  8. [android] 百度地图开发 (三).定位当前位
  9. 自定义实现向量图标动画VectorDrawable
  10. fir.im Weekly - 暖心的 iOS 持续集成,你