开发实用技巧
1 tools:listitem="@layout/item_cv_fragment_start"
2.androidstudio的源文件保存:
as的源码需要拷贝出来时,不要直接去该项目所在路径复制源文件,一定要看清楚该路径下是否是最新编辑的源文件,可能不是(坑惨了)
3.重新安装JDK:
重新安装了JDK,为了不影响之前的JDK,应该把%JAVA_HOME%在path中的路径上移到最上面,JAVA_HOME还是采用之前的,然后在实际中选择特定的JDK.如图:
4.MAVEN版本与JDK安装版本不兼容
MAVEN版本需要与JDK版本不兼容可以在eclipse中重新制定相兼容的版本的JDK就行了
3.spring中@Autowired注解与@Resource(这是java中的注解)的使用区别:
@Autowired是spring中的自动注入,如果是一个接口一个实现类,需在实现类中上面引入@Service,再引入@Autowired时系统自动找到该接口的实现类,但是如果有多个接口就会出错,只能用@Resource(“xxx”)注入指定的实现,且实现接口需要用@Service(“xxx”)
4.maven默认采用tomcat6端口,下面修改路径和端口
<build>
<plugins>
<!-- maven内置 的tomcat6插件 -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>tomcat-maven-plugin</artifactId>
<version>1.1</version>
<configuration>
<!-- 可以灵活配置工程路径 -->
<path>/ssh</path>
<!-- 可以灵活配置端口号 -->
<port>8080</port>
</configuration>
</plugin>
</plugins>
</build>
5.ObjectAnimotor的x,y,width,height偏移:
(1).如果没有水平方向的偏移,width的拉升默认是向正方向(右边)拉升;
ObjectAnimator.ofFloat(newBall,"width", newBall.getWidth(),newBall.getWidth()+BALL_SIZE);
(2).如果有x方向偏移,width的方向是按照x的移动方向拉升,比如
ObjectAnimator.ofFloat(newBall, "x", newBall.getX(), newBall.getX() -BALL_SIZE/2);
这是向左移动,所以width如果拉升BALL_SIZE个长度的话,拉升先满足向左BALL_SIZE/2,还有BALL_SIZE/2只能是向右了
(3).onDraw()
@Override
protected void onDraw(Canvas canvas)
{
// 遍历balls集合中的每个ShapeHolder对象
for (ShapeHolder shapeHolder : balls)
{
// 保存canvas的当前坐标系统
canvas.save();
// 坐标变换:将画布坐标系统平移到shapeHolder的X、Y坐标处
canvas.translate(shapeHolder.getX(), shapeHolder.getY());
// 将shapeHolder持有的圆形绘制在Canvas上
shapeHolder.getShape().draw(canvas);
// 恢复Canvas坐标系统
canvas.restore();
}
}
(4).ShapHolder中height,width发生改变,都需要重新定义大小,小球在移动的过程中就一直调用shape的绘制
public void setHeight(float height)
{
Shape s = shape.getShape();
Log.i(TAG, "setHeight: -------s.getWidth():"+s.getWidth()+",height:"+height);
s.resize(s.getWidth(), height);
}
public void setWidth(float width)
{
Log.i(TAG, "setWidth: -------调用了");
Shape s = shape.getShape();
s.resize(width, s.getHeight());
}
(5).点睛之笔
在构造方法中,开启一个背景变化,且是无限循环的,这样改View的onDraw方法就一直在执行,下来的任意操作后都会有onDraw()的重绘
public MyAnimationView(Context context)
{
super(context);
// 加载动画资源
ObjectAnimator colorAnim = (ObjectAnimator) AnimatorInflater
.loadAnimator(MainActivity.this, R.animator.color_anim);
colorAnim.setEvaluator(new ArgbEvaluator());
// 对该View本身应用属性动画
colorAnim.setTarget(this);
// 开始指定动画
colorAnim.start();
}
(6).如果没有上面操作,可以设置动画更新监听,在其中来不断重绘
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
// 指定重绘该界面
this.invalidate(); // ①
}
6.RecyclerView刷新数据:
private void addData(){
List<MultiItemEntity> list=new ArrayList<>();
list.add(new Person("新增1", 111));
list.add(new Person("新增2", 222));
int index=6;
mRes.addAll(index+1,list);
adapter.notifyItemChanged(index);
adapter.notifyItemRangeInserted(index + 1, list.size());
}
7.属性xml动画:
(1).
(2).实例popshow.xml
以自身为基础,Y正方向向上,100%~0表示,加p表示的是以父容器为标准,不加p则是以自身为标准,所以最终结果是移动自身的100%p就完全可见了
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!--以自身为基础,Y正方向向下,20%~0表示向上移动,p自身的距离,所以最终结果是移动自身的20%p就完全不见了-->
<translate
android:duration="3500"
android:fromYDelta="100%"
android:toYDelta="0" />
<alpha
android:duration="3500"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!--以自身为基础,Y正方向向下,0~20%表示向下移动,p自身的距离,所以最终结果是移动自身的20%p就完全不见了-->
<translate
android:duration="3500"
android:fromYDelta="0"
android:toYDelta="100%" />
<alpha
android:duration="3500"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
(4).效果图
(5).坐标标准:
8.View绘制流程(TimeLineView为例)
(1).计算小球的合理直径:
int pLeft = getPaddingLeft();
int pRight = getPaddingRight();
int pTop = getPaddingTop();
int pBottom = getPaddingBottom();
int width = getWidth();// Width of current custom view
int height = getHeight();
int cWidth = width - pLeft - pRight;// Circle width
int cHeight = height - pTop - pBottom;
int markSize = Math.min(mMarkerSize, Math.min(cWidth, cHeight));
(2).计算小球在控件中的绘制范围:
if(mMarkerInCenter) { //居中显示情况
if(mMarker != null) {
mMarker.setBounds((width/2) - (markSize/2),(height/2) - (markSize/2), (width/2) + (markSize/2),(height/2) + (markSize/2));
mBounds = mMarker.getBounds();
}
} else { //水平居中,但是垂直根据mStartMaginTop来合理调整距离顶部的高度
if(mMarker != null) {
mMarker.setBounds((width/2) - (markSize/2),mStartMaginTop, (width/2) + (markSize/2),markSize+mStartMaginTop);
mBounds = mMarker.getBounds();
}
}
(3).绘制小球上下线,以小球为基准
//TODO:注意,我这里只考虑了垂直方向的情况,水平方向按这个思路同理
int centerX = mBounds.centerX();
int lineLeft = centerX - (mLineSize >> 1);
if(mLineOrientation==0) {
//水平方向
if(mStartLine != null) {
mStartLine.setBounds(0, pTop + (mBounds.height()/2), mBounds.left - mLinePadding, (mBounds.height()/2) + pTop + mLineSize);
}
if(mEndLine != null) {
mEndLine.setBounds(mBounds.right + mLinePadding, pTop + (mBounds.height()/2), width, (mBounds.height()/2) + pTop + mLineSize);
}
} else {
//垂直方向
if(mStartLine != null) {
//TODO:方式一:根据控件顶部(0,0)为基准点来绘制
mStartLine.setBounds(lineLeft, 0, mLineSize + lineLeft, mBounds.top - mLinePadding);
//TODO:方式二:根据底部(lineLeft, mBounds.top - mLinePadding)为基准点来绘制
//mStartLine.setBounds(lineLeft, mBounds.top - mLinePadding-((height-markSize)>>1), mLineSize + lineLeft, mBounds.top - mLinePadding);
}
if(mEndLine != null) {
mEndLine.setBounds(lineLeft, mBounds.bottom + mLinePadding, mLineSize + lineLeft, height);
}
}
(4).onMesure方法记得需要重新测绘:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//内部的padding需要自己去计算,重新设置进去
int w = mMarkerSize + getPaddingLeft() + getPaddingRight();
int h = mMarkerSize + getPaddingTop() + getPaddingBottom();
// 宽度和高度通过系统的决策方式来确定最终的视图宽高
int widthSize = resolveSizeAndState(w, widthMeasureSpec, 0);
int heightSize = resolveSizeAndState(h, heightMeasureSpec, 0);
setMeasuredDimension(widthSize, heightSize);
initDrawable();
}
(5).大小改变时也需要initDrawable():
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
initDrawable();
}
(6).最后就是onDraw()方法了
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(mMarker != null) {
mMarker.draw(canvas);
}
if(mStartLine != null) {
mStartLine.draw(canvas);
}
if(mEndLine != null) {
mEndLine.draw(canvas);
}
}
(7).自定义属性
(8)xml布局:
图1 默认居中显示 图2 marginTop 5dp
(9).效果图:
图1居中显示 图2 水平居中,marginTop一小段距离5dp