Android实现View选中状态添加有动画效果的边框

应用场景

最近开发了一个标签编辑APP,用户可以往编辑区域添加文本、条形码、二维码、图片等元素,然后对这些元素的位置、大小、内容等属性进行设置,最终设计出各种不同的标签界面。

标签编辑APP主界面

在编辑区中,当需要对某一个View元素调整属性参数时,首先要选中该View,让选中的View显示一个边框,以表示选中状态。例如上图中的那一串ID字符串,当选中这个元素后,给这个TextView添加了一个虚线边框。

添加了一个静态的边框后,为了达到更好的用户体验效果,我思考着给这个边框添加一个动画效果,很自然地联想到Photoshop处理图片时,那种选中区域轮廓上显示一个流动的虚线线条的效果。这也正是我希望达到的效果。

一番搜索之后,几乎没有找到有用的参考范例。静下心思考之后,Android中常用的渐变动画、帧动画、属性动画,貌似都无法实现这种想要的效果。在这个过程中,感觉最有可能的是SVG动画实现,但因为确实不熟悉这部分,因时间关系未做深究。

经过间断性地持续努力,找到了一种变通的做法,准确来说,这并不是动画,而是在观感上达到了想要实现的类似效果,并且,效果还不错。

下面,说一下我的实现方法。

添加边框

首先,给View添加静态虚线边框,因为是选中状态的View才添加边框,即获得焦点或点击View之后,给该View添加一个边框,失去焦点时不显示边框。由此想到给View设置一个根据状态变化的background,即selector。

使用view_background.xml定义selector,selector中不同的状态定义不同的shape元素。代码如下:

<?xml version="1.0" encoding="utf-8"?>

	
	    
		    
		    
		     
		    
		    
		    
		    
		    
		     
		    
		    
		    
		    
		
	
	
	    
		    
		    
		     
		    
		    
		    
		    
		    
		     
		    
		    
		    
		    
		
	
	
	    
		    
		    
		    
		     
		    
		    
		     
		    
		    
		    
		    
		
	

在这个selector中,定义了矩形shape,矩形不填充颜色。当android:state_pressed为true或android:state_focused为true时,设置shape有边框线,当他们为false时,设置shape无边框线。

对于编辑区的所有View,都设置background为view_background.xml,这样便实现了View选中时有边框,失去焦点时无边框。

下一步,就是给这个边框添加“动画”效果了。

实现动画边框

实现动画边框效果的思路,来自于我对虚线边框样式的调整过程中。我注意到上面定义的shape虚线边框中,可以通过改变android:dashWidth、android:dashGap两项参数,即虚线条的长度和虚线条之间的间隔宽度来改变虚线条的样式。

所以,我就想到了通过不断变换这两个参数,来实现边框展示出一种“动画”效果。

首先,我们需要知道,上面xml定义的selector,对应于Android API中的GradientDrawable,可以通过下面的方式将selector资源转换为GradientDrawable:

//将XML定义的selector资源加载为GradientDrawable对象
GradientDrawable gradientDrawable = (GradientDrawable)getDrawable(R.drawable.view_background);

然后,通过代码改变虚线条的长度和虚线条之间的间隔:

//setStroke方法可改变线条的粗细、颜色、虚线条的长度和虚线条之间的间隔
gradientDrawable.setStroke(width, color, dashWidth, dashGap);

GradientDrawable对象的setStroke方法,接收4个参数,分别表示线条的粗细、颜色、虚线条的长度和虚线条之间的间隔,如果dashWidth, dashGap都为0,则表示实线。

在我预期的效果中,线条的粗细、颜色都不变,只是改变dashWidth, dashGap这两个参数。

要实现边框的“动画”效果,需要不断地改变这两项参数。我分别定义了三组参数:

//定义3个不同的虚线条长度
private float[] dashwidth = new float[]{15F, 14F, 13F};
//定义3个不同的虚线条之间的间隔
private float[] dashGap = new float[]{3F, 2.8F, 2.6F};

如果需要变换线条颜色,也可以定义一组颜色:

//定义3个不同的颜色
private int[] strokeColor = new int[]{Color.parseColor("#FF0000"), Color.parseColor("#00FF00"), Color.parseColor("#0000FF")};

动态改变边框样式:

int borderStyleIndex = 0;

private Runnable borderChangeRunnable = new Runnable(){
  @Override
  public void run() {
    if (selectedView != null) {				
      StateListDrawable drawable = (StateListDrawable)selectedView.getBackground();
      GradientDrawable gradientDrawable = (GradientDrawable)drawable.getCurrent();
      borderStyleIndex = (borderStyleIndex + 1) % 3;
      gradientDrawable.setStroke(4, strokeColor[borderStyleIndex], dashwidth[borderStyleIndex], dashGap[borderStyleIndex]);
      selectedView.postDelayed(this, BORDER_STYLE_INTERVAL);
  }
 }
};

上面的selectedView表示当前选中的View。当View获取焦点或被点击后,只需这样调用:

//“动画”间的间隔时间
private static long BORDER_STYLE_INTERVAL = 600;
//改变选中View的边框
selectedView.postDelayed(borderChangeRunnable, BORDER_STYLE_INTERVAL);

这样,便实现了“动画”边框的效果。最初的预期的效果是虚线框看起来是一个顺时针流动的线条,这种实现方法与此有差距,不过通过微调上面定义的几组参数,在观感上可以达到近似的效果。

对于这一效果的实现,不知大家有没有更好的办法呢?

展开阅读全文

页面更新:2024-02-04

标签:边框   效果   动画   虚线   间隔   线条   长度   定义   颜色   状态   参数

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top