最近安卓开发中需要让一个图片旋转,需要做一个圆形的进度条。为了让测试不那么枯燥,做了一个时钟。
效果图
时间的显示主要用到两个功能:1、获取系统时间;2、旋转指针。
主类代码如下:
package com.example.androidtest2; import java.util.Calendar; import android.annotation.SuppressLint; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; import android.widget.TextView; /** * @author 作者:hanyeah * @date 创建时间:2017-3-1 上午11:51:48 */ public class MainActivity extends Activity { private BiaopanView biaopan; private BiaopanView progressView; private ImageView shizhen; private ImageView fenzhen; private ImageView miaozhen; private float x; private float y; private TextView tv; public MainActivity() { // TODO Auto-generated constructor stub } @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv=(TextView)findViewById(R.id.tv); shizhen=(ImageView)findViewById(R.id.shizhen); fenzhen=(ImageView)findViewById(R.id.fenzhen); miaozhen=(ImageView)findViewById(R.id.miaozhen); biaopan=(BiaopanView)findViewById(R.id.biaopan); progressView=(BiaopanView)findViewById(R.id.biaopan); biaopan.setOnClickListener(new View.OnClickListener() { @SuppressLint("NewApi") @Override public void onClick(View v) { // TODO Auto-generated method stub int w=v.getWidth(); int h=v.getHeight(); Log.d("hanyeah",String.format("w=%d,h=%d,x=%f,y=%f", w,h,x,y)); float angle=(float) Math.atan2(y-h/2,x-w/2); tv.setText("角度:"+angle*180/Math.PI); } }); biaopan.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub x=event.getX(); y=event.getY(); return false; } }); hd.sendEmptyMessageDelayed(1, 1); } private Handler hd=new Handler(){ public void handleMessage(android.os.Message msg) { updateBiaopan(); hd.sendEmptyMessageDelayed(1, 1000); }; }; private float angle=0; @SuppressLint("NewApi") private void updateBiaopan(){ Calendar c = Calendar.getInstance(); int hour=c.get(Calendar.HOUR); int minute=c.get(Calendar.MINUTE); int secend=c.get(Calendar.SECOND); shizhen.setRotation(hour*30+minute*30f/60f); fenzhen.setRotation(minute*6); miaozhen.setRotation(secend*6); progressView.progress=secend*6; progressView.invalidate(); } }
还多测试了一个功能,点击表盘,显示点击位置与表盘中心连线的角度(相对于哪个轴不重要,按需求映射就行)。
指针旋转实现起来太简单了,一个setRotation方法就可以了。具体实现起来可能需要一些技巧,有问题的话可以下载附件。
圆形的进度条(蓝色)是重写表盘的draw方法来实现的。
代码如下:
package com.example.androidtest2; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.ImageView; /** * @author 作者:hanyeah * @date 创建时间:2017-3-1 下午4:43:09 */ public class BiaopanView extends ImageView { public BiaopanView(Context context) { super(context); // TODO Auto-generated constructor stub } public BiaopanView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public BiaopanView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub } @Override public void draw(Canvas canvas) { // TODO Auto-generated method stub super.draw(canvas); //画笔。 Paint p = new Paint(); p.setAntiAlias(true);//平滑 p.setColor(Color.BLUE);// 设置红色 p.setStyle(Paint.Style.STROKE);//画线,不填充 p.setStrokeWidth(10);//线的粗细 //图片显示的宽高,根据布局计算,可能会变形 int w=this.getMeasuredWidth(); int h=this.getMeasuredHeight(); //默认宽高,即图片的实际尺寸。 int defaultW=661; int defaultH=618; float hw=defaultW/2; float hh=defaultH/2; //针的直径 int zhenW=536; int hZhenW=zhenW/2; int zhenH=526; int hZhenH=zhenH/2; canvas.save(); canvas.scale(w/(float)defaultW, h/(float)defaultH); RectF oval1=new RectF(hw-hZhenW,hh-hZhenH,hw+hZhenW,hh+hZhenH); canvas.drawArc(oval1, -90, progress, false, p);//小弧形 canvas.restore(); } public float progress=0f; }
这里直接在显示表盘的类里面画进度条,而不是进度条自己占用一个显示控件,这样是有好处的。
具体可以参考源码,现在看来,实现的还是比较巧妙的。自己体会吧。
不一定要继承ImageView,继承View也行,由于我在xml布局中设置了src属性,所以用的ImageView。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。