MainActivity中代码如下,我都做了相关的注释,很清晰
package com.safly.myapplication;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.graphics.Color;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.app.WindowDecorActionBar;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.BounceInterpolator;
import android.view.animation.OvershootInterpolator;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import org.w3c.dom.Text;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
ImageView dele_update_tip;
Button atOnceUpdate;
ScrollView mScrollView;
LinearLayout mScrollViewLL;
RelativeLayout update_container;
TextView updateView;
float updateContainerH;
int updateTextScrollH;
int perH;
List<String> updateInfos;
int measuredHeight;
int height;
private Handler mHandler = new Handler();
private MyRun myRun = new MyRun();
/**
* 这里进行视图滚动的设置操作
* 方法是:动画结束1秒后开始滚动
* 然后100毫秒重复一次,每次位移是1dp
*当scrollview屏幕内可显示的高度+位移高度<=总高度时候就一直循环移动移动
* 相反呢就回归原位继续循环滚动视图文本
*/
class MyRun implements Runnable{
@Override
public void run() {
Log.i("MainActivity","---updateTextScrollH---"+updateTextScrollH+",height---"+height+",measuredHeight--"+measuredHeight);
updateTextScrollH = updateTextScrollH + perH;
if (updateTextScrollH + height<=measuredHeight){
mScrollView.scrollTo(0,updateTextScrollH);
mHandler.postDelayed(myRun, 100);
}else{
mScrollView.scrollTo(0,0);
mHandler.removeCallbacks(myRun);
updateTextScrollH = 0;
if (height> measuredHeight){
return;
}
mHandler.postDelayed(myRun, 100);
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initRes();
initUpdateInfo();
mesure();
addScrollViewUpdateInfos();
initUpdateContainerAni();
/**
*这里也需要进行操作
*donw时:去掉myrun然后定位到移动到的位置
*move:获取当时的位置,移动到即可
* up:更新位置 开始循环滚动视图
*
*/
mScrollView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mHandler.removeCallbacks(myRun);
mScrollView.scrollTo(0,updateTextScrollH);
Log.i(TAG,"-----ACTION_DOWN updateTextScrollH-----"+updateTextScrollH);
break;
case MotionEvent.ACTION_MOVE:
// int moveY = (int) event.getY();
// mScrollView.scrollTo(0,moveY);
break;
case MotionEvent.ACTION_UP:
float scaleY = mScrollView.getScrollY();
updateTextScrollH = (int) scaleY;
Log.i(TAG,"-----ACTION_UP updateTextScrollH-----"+updateTextScrollH);
mHandler.postDelayed(myRun,1000);
break;
}
return false;
}
});
}
/**
* 获取控件资源
*/
private void initRes() {
dele_update_tip = (ImageView) findViewById(R.id.dele_update_tip);
dele_update_tip.setOnClickListener(this);
atOnceUpdate = (Button) findViewById(R.id.update);
atOnceUpdate.setOnClickListener(this);
mScrollView = (ScrollView) findViewById(R.id.mScrollView);
mScrollViewLL = (LinearLayout) findViewById(R.id.mScrollView_LL);
update_container = (RelativeLayout) findViewById(R.id.update_container);
}
/**
* 为ScrollView中的addView操作,随机添加5条textView文本数据
*/
private void initUpdateInfo() {
updateInfos = new ArrayList<>();
for (int i =0;i<5;i++){
updateInfos.add((i+1)+"--"+MeasureUtil.getRandomString((int)(1+Math.random()*(10-1+1))));
}
}
/**
* 初始化视图从屏幕外弹出来,测量高度,高度直接就从xml写死了,当然可以通过代码进行获取控件高度
* 可以通过addOnGlobalLayoutListener、post(run)、onWindowFocusChanged
*/
private void mesure() {
updateContainerH = DisplayUtil.dip2px(this, 230);
perH = DisplayUtil.dip2px(this, 1f);
}
/**
* 为scrollview添加数据addView
*/
private void addScrollViewUpdateInfos() {
if (mScrollView !=null ){
View view0 = mScrollView.getChildAt(0);
if (view0 instanceof LinearLayout){
mScrollViewLL = (LinearLayout) view0;
for (int i = 0;i<updateInfos.size();i++){
updateView = null;
updateView = new TextView(this);
updateView.setText(updateInfos.get(i));
updateView.setTextColor(Color.parseColor("#8E8E8E"));
mScrollViewLL.addView(updateView);
}
}
}
}
/**
* 利用ValueAnimator动画,在addUpdateListener中设置插值器
* 当动画结束后,1秒后开始滚动scrollView里面的视图文本
* 然后循环滚动即可
*
* 这里获取了2个值
* measuredHeight:mscrollview的全部高度
* height:屏幕能看见的scrollview高度
*/
private void initUpdateContainerAni() {
ValueAnimator updateContainerAni = ValueAnimator.ofFloat(-updateContainerH,0);
updateContainerAni.setInterpolator(new BounceInterpolator());
updateContainerAni.setTarget(update_container);
updateContainerAni.setDuration(1500).start();
updateContainerAni.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
update_container.setTranslationY((Float) animation.getAnimatedValue());
}
});
updateContainerAni.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
measuredHeight = mScrollViewLL.getMeasuredHeight();
height = mScrollView.getHeight();
Log.i("MainActivity","height--"+height+",measuredHeight--"+measuredHeight);
mScrollView.scrollTo(0,0);
mHandler.postDelayed(myRun,1000);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.dele_update_tip:
finish();
break;
case R.id.update:
Toast.makeText(MainActivity.this,"update",Toast.LENGTH_LONG).show();
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(myRun);
mHandler = null;
}
}
然后是布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#4B0082"
tools:context="com.safly.myapplication.MainActivity">
<RelativeLayout
android:id="@+id/update_container"
android:layout_width="300dp"
android:layout_height="230dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true">
<ImageView
android:id="@+id/dele_update_tip"
android:layout_alignParentRight="true"
android:padding="12dp"
android:src="@mipmap/x"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:background="@mipmap/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/x_update"
android:typeface="normal"
android:layout_marginLeft="96dp"
android:textSize="18dp"
android:textStyle="bold"
android:layout_marginTop="50dp"
android:textColor="#458B74"
android:text="X分身更新了"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:textColor="#8E8E8E"
android:id="@+id/text_update"
android:layout_alignLeft="@id/x_update"
android:layout_below="@id/x_update"
android:text="更新内容:"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ScrollView
android:id="@+id/mScrollView"
android:scrollbars="none"
android:layout_alignLeft="@id/text_update"
android:layout_below="@id/text_update"
android:layout_centerHorizontal="true"
android:layout_width="100dp"
android:layout_height="60dp">
<LinearLayout
android:id="@+id/mScrollView_LL"
android:orientation="vertical"
android:layout_width="100dp"
android:layout_height="60dp">
</LinearLayout>
</ScrollView>
</RelativeLayout>
<Button
android:id="@+id/update"
android:textStyle="bold"
android:textColor="#ffffff"
android:textSize="20dp"
android:text="立即更新"
android:layout_marginLeft="84dp"
android:layout_alignParentBottom="true"
android:background="@mipmap/update"
android:layout_width="wrap_content"
android:layout_height="40dp" />
</RelativeLayout>
</RelativeLayout>
最后2个工具类
DisplayUtil
package com.safly.myapplication;
import android.content.Context;
public final class DisplayUtil {
/**
* 将px值转换为dip或dp值,保证尺寸大小不变
*
* @param pxValue
* @param context
* (DisplayMetrics类中属性density)
* @return
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 将dip或dp值转换为px值,保证尺寸大小不变
*
* @param dipValue
* @param context
* (DisplayMetrics类中属性density)
* @return
*/
public static int dip2px(Context context, float dipValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
/**
* 将px值转换为sp值,保证文字大小不变
*
* @param pxValue
* @param context
* (DisplayMetrics类中属性scaledDensity)
* @return
*/
public static int px2sp(Context context, float pxValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
/**
* 将sp值转换为px值,保证文字大小不变
*
* @param spValue
* @param context
* (DisplayMetrics类中属性scaledDensity)
* @return
*/
public static int sp2px(Context context, float spValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
}
MeasureUtil
package com.safly.myapplication;
import android.app.Activity;
import android.util.DisplayMetrics;
import java.util.Random;
/**
* 测绘工具类
*/
public final class MeasureUtil {
/**
* 获取屏幕尺寸
*
* @param activity
* Activity
* @return 屏幕尺寸像素值,下标为0的值为宽,下标为1的值为高
*/
public static int[] getScreenSize(Activity activity) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
return new int[] { metrics.widthPixels, metrics.heightPixels };
}
public static String getRandomString(int length) { //length表示生成字符串的长度
String base = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
}