1. 简单方法加动效,拒绝生硬

(1) 如何用一行代码加动效:

android:animateLayoutChanges="true"

开启系统默认动画效果,在每次布局发生变化的时候生效,让布局的变化过渡看起来更自然。试一下,有惊喜!

(2) 自定义LayoutAnimation:

//初始化LayoutAnimationController
private LayoutAnimationController getAnimationController() {
    final int duration = 180; //动画时长
    AnimationSet set = new AnimationSet(true);
		
	//渐变动画
    Animation animation = new AlphaAnimation(0.0f, 1.0f);
    animation.setDuration(duration);
    set.addAnimation(animation);
	//平移动画
    animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,-1.0f, Animation.RELATIVE_TO_SELF, 0.0f);
    animation.setDuration(duration);
    set.addAnimation(animation);

    LayoutAnimationController animationController = new LayoutAnimationController(set, 0.5f);
    animationController.setOrder(LayoutAnimationController.ORDER_NORMAL);
    return animationController;
}
...
//设置LayoutAnimation
View.setLayoutAnimation(getAnimationController();
//显式调用LayoutAnimation
View.startLayoutAnimation();

LayoutAnimation作用于View,可以自定义组合动画,显式调用动画。若对系统动画不满意,可以根据自己的需求写出动画效果。

2. 一行代码加入点击波纹扩散效果

android:foreground="?android:attr/selectableItemBackground"

3. 屏蔽快速点击、重复事件

用于屏蔽快速点击,短时间内的重复多余的事件、双击退出等,避免手动管理。

/**
 * 屏蔽快速重复操作事件
 */
private static long lastTime;
private static final int MIN_DELAY_TIME = 1000;

public static boolean isQuickOperating() {
    boolean flag = true;
    long currentTime = System.currentTimeMillis();
    if ((currentTime - lastTime) >= MIN_DELAY_TIME) {
        flag = false;
    }
    lastTime = currentTime;
    return flag;
}

4. 判断当前Activity是否已被销毁

通常,在网络请求的回调中会对UI进行更新操作,弹出吐司等。但是在网络状态不佳的情况下,等到异步结果回调时,当前Activity已经被系统销毁,此时进行UI操作就会造成异常,弹出的吐司也让人疑惑。所以,在网络回调中需要先判断一下当前Activity状态,若已销毁,直接return。代码片段如下:

if (this.isFinishing() || this.isDestroyed()) {
            return;
        }

源码及注释:

/**
  * Check to see whether this activity is in the process of finishing,
  * either because you called {@link #finish} on it or someone else
  * has requested that it finished.  This is often used in
  * {@link #onPause} to determine whether the activity is simply pausing or
  * completely finishing.
  *
  * @return If the activity is finishing, returns true; else returns false.
  *
  * @see #finish
  */
 public boolean isFinishing() {
     return mFinished;
 }

 /**
  * Returns true if the final {@link #onDestroy()} call has been made
  * on the Activity, so this instance is now dead.
  */
 public boolean isDestroyed() {
     return mDestroyed;
 }

5. 使用SystemClock.sleep()替代Thread.sleep()

两者使用方法跟作用都类似,但SystemClock.sleep()不会立即抛出InterruptedException,中断事件被推迟到下一个可中断操作中。 可以说非常适合简单的延迟操作了,不用频繁。(说的好像Thread.sleep()方法Try Catch了Exception真的会做什么一样......

6. 线程池的简单使用

原始粗放的形式:

new Thread(new Runnable() {
	@Override
	public void run() {
        // TODO
    	Log.e("run");
	}
}).start();

合理科学的形式:

Runnable command = new Runnable(){
	@Override
	public void run(){
		// TODO
    	Log.e("run");
	}
};
//定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
fixedThreadPool.execute(command);
//可缓存线程池,如果线程池长度超出需求,可灵活回收空闲线程,若无线程可回收,则新建
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
cachedThreadPool.execute(command);
//定长线程池,支持定时及周期性任务执行
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4);
// 2000ms后执行
scheduledExecutorService.schedule(command,2000,TimeUnit.MILLISECONDS);
// 延迟10ms后,每隔1000ms执行一次command
scheduledExecutorService.scheduleAtFixedRate(command,10,1000,TimeUnit.MILLISECONDS);
//单线程化线程池,使用唯一工作线程来执行任务,保证所有任务按顺序执行
ExecutorService singleThreadExecutor = Executor.newSingleThreadExecutor;
singleThreadExecutor.execute(command);

7. 自定义BuildConfig字段,方便查看版本信息

buildTypes {
        release {
            minifyEnabled true 
            shrinkResources true
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
			//自定义BuildConfig字段,可通过BuildConfig.buildTime取出,方便查看编译信息
            buildConfigField("String", "buildTime", "\"" + new Date().format("yyyy/MM/dd HH:mm:ss") + "\"")
        }
	}

在应用内埋个彩蛋,结合VERSION_CODE、VERSION_NAME、BUILD_TYPE,就可以方便查看当前APP的版本相关信息了!

8. 模拟点击View

这个功能不多说了,实用!

/**
 * 模拟点击,点击该View的xy坐标(5,5)
 *
 * @param view 模拟点击的View
 */
public static void simulateTouch(View view) {
	
    final long downTime = SystemClock.uptimeMillis();
    int[] ints = new int[2];
    view.getLocationOnScreen(ints);
    view.dispatchTouchEvent(MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN,
            ints[0] + 5, ints[1] + 5, 0));
    view.dispatchTouchEvent(MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_UP,
            ints[0] + 5, ints[1] + 5, 0));
			
}

9. 使用tools属性工具预览布局

tools属性仅对IDE生效,并不会影响最终打包的应用。
比如:
TextView需要预览内容,可以使用tools:text属性;
如果ImageView默认不显示,而你又要预览,就可以使用tools:visibility属性,避免改动android:visibility过后忘记改回去的尴尬。其他更多用法可以自己去尝试了。

<TextView
  android:id="@+id/bus_time_textView"
  android:layout_width="100dp"
  android:layout_height="match_parent"
  android:layout_gravity="center"
  android:gravity="center"
  android:textColor="@color/text_default"
  android:textSize="15sp"
  tools:text="30分钟" />

<ImageView
  android:id="@+id/less_time_imageView"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:background="@drawable/icon_the_fastest"
  tools:visibility="visible"
  android:visibility="gone" />

上海市app开发迅速网络科技有限公司,专注APP开发14年,专业开发服务和上百家企业的IT项目经 验,为用户提供在短时间内达到商务目标的各类优质产品解决方案,开发出用户喜欢的移动app

  通过我们强大且专业的技术研发团队,多线程快速地开发产品并保证产品及时上线;

我们还提供产品后期运营,维护和推广等一站式服务的高端解决方案。

  如果您有一个外部的创意和想法,想要做出自己的产品时,请联系我们:

021-64391578 张经理