主要是记录一下项目中的一些效果,方便以后同样的需求直接过来copy
看到这个需求的时候去网上找了好久,都是一个textView的滚动,满足不了需求.
最后只能动手了,原来很简单,就是2个view来回倒腾,搞个动画,就行了
布局
2个LinearLayout,里面放了TextViw,隐藏其中一个LinearLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_notice1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="烟花易冷"
android:maxLines="1"
android:ellipsize="end"
android:textColor="#ff333333"
android:textSize="18sp" />
<TextView
android:id="@+id/tv_content1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="繁华声遁入空门折煞了庶人"
android:maxLines="1"
android:layout_marginTop="3dp"
android:ellipsize="end"
android:textColor="#ff999999"
android:textSize="16sp"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/ll_notice2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="烟花易冷"
android:maxLines="1"
android:ellipsize="end"
android:textColor="#ff333333"
android:textSize="18sp" />
<TextView
android:id="@+id/tv_content2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="繁华声遁入空门折煞了庶人"
android:maxLines="1"
android:layout_marginTop="3dp"
android:ellipsize="end"
android:textColor="#ff999999"
android:textSize="16sp"
/>
</LinearLayout>
</RelativeLayout>
LinearLayout出去的动画,向上平移,平移出去就隐藏
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="2000"
android:fillAfter="true"
android:fromXDelta="0%"
android:fromYDelta="100%"
android:toXDelta="0%"
android:toYDelta="0%" />
</set>
private void notice1OutAnim() {
llNotice1.startAnimation(mSlide_Out);
llNotice1.setVisibility(View.INVISIBLE);
if ((++item) == mDataList.size()) {
item = 0;
}
tvTitle2.setText(mTitleList.get(item));
tvContent2.setText(mDataList.get(item));
llNotice2.setVisibility(View.VISIBLE);
llNotice2.startAnimation(mSlide_In);
isOne = false;
}
进来的动画,从下往上平移
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="2000"
android:fillAfter="true"
android:fromXDelta="0%"
android:fromYDelta="0%"
android:toXDelta="0%"
android:toYDelta="-100%" />
</set>
private void notice2OutAnia() {
llNotice2.startAnimation(mSlide_Out);
llNotice2.setVisibility(View.INVISIBLE);
if ((++item) == mDataList.size()) {
item = 0;
}
tvTitle1.setText(mTitleList.get(item));
tvContent1.setText(mDataList.get(item));
llNotice1.setVisibility(View.VISIBLE);
llNotice1.startAnimation(mSlide_In);
isOne = true;
}
然后用一个Handler来回倒腾动画
class MyHandler extends Handler implements Runnable {
@Override
public void run() {
if (isOne) {
notice1OutAnim();
} else {
notice2OutAnia();
}
mHandler.postDelayed(this, DURATION);
}
}
整体的代码
package com.duanlian.demos;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class VerticalMarqueeLayout extends LinearLayout implements OnClickListener {
private static final long DURATION = 3000;
private MyHandler mHandler;
private List<String> mDataList;
private List<String> mTitleList;
private Context mContext;
private boolean isOne = true;
private LinearLayout llNotice1;
private LinearLayout llNotice2;
private Animation mSlide_In;
private Animation mSlide_Out;
private TextView tvTitle1, tvContent1;
private TextView tvTitle2, tvContent2;
private int item = 0;// 标志位
/**
* 构造函数
*/
public VerticalMarqueeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mHandler = new MyHandler();
mContext = getContext();
View layout = LayoutInflater.from(mContext).inflate(R.layout.layout_textview, this);
tvTitle1 = layout.findViewById(R.id.tv_title1);
tvContent1 = layout.findViewById(R.id.tv_content1);
tvTitle2 = layout.findViewById(R.id.tv_title2);
tvContent2 = layout.findViewById(R.id.tv_content2);
llNotice1 = layout.findViewById(R.id.ll_notice1);
llNotice2 = layout.findViewById(R.id.ll_notice2);
llNotice1.setOnClickListener(this);
llNotice2.setOnClickListener(this);
mSlide_Out = AnimationUtils.loadAnimation(mContext, R.anim.slide_in);
mSlide_In = AnimationUtils.loadAnimation(mContext, R.anim.slide_out);
}
/**
* 对外,设置文本数据
*/
public void setData(List<String> titles, List<String> list) {
this.mDataList = list;
this.mTitleList = titles;
// 非空判断
if (mDataList == null || mDataList.size() < 2) {
mDataList = new ArrayList<>();
mDataList.add("通知一");
mDataList.add("通知二");
}
tvTitle1.setText(mTitleList.get(0));
tvContent1.setText(mDataList.get(0));
tvTitle1.setText(mTitleList.get(1));
tvContent2.setText(mDataList.get(1));
}
/**
* 开始执行
*/
public void startRun() {
mHandler.post(mHandler);
}
class MyHandler extends Handler implements Runnable {
@Override
public void run() {
if (isOne) {
notice1OutAnim();
} else {
notice2OutAnia();
}
mHandler.postDelayed(this, DURATION);
}
}
private void notice1OutAnim() {
llNotice1.startAnimation(mSlide_Out);
llNotice1.setVisibility(View.INVISIBLE);
if ((++item) == mDataList.size()) {
item = 0;
}
tvTitle2.setText(mTitleList.get(item));
tvContent2.setText(mDataList.get(item));
llNotice2.setVisibility(View.VISIBLE);
llNotice2.startAnimation(mSlide_In);
isOne = false;
}
private void notice2OutAnia() {
llNotice2.startAnimation(mSlide_Out);
llNotice2.setVisibility(View.INVISIBLE);
if ((++item) == mDataList.size()) {
item = 0;
}
tvTitle1.setText(mTitleList.get(item));
tvContent1.setText(mDataList.get(item));
llNotice1.setVisibility(View.VISIBLE);
llNotice1.startAnimation(mSlide_In);
isOne = true;
}
@Override
public void onClick(View view) {
if (click != null) {
click.onItemClick(item);
}
}
public interface ItemClick {
void onItemClick(int position);
}
ItemClick click;
public void setOnItemClick(ItemClick onItemClick) {
this.click = onItemClick;
}
}
在activity里设置数据,触发动画,设置点击事件
private void initView() {
vmLayout = findViewById(R.id.vertical_marquee);
titleList = new ArrayList<>();
contentList = new ArrayList<>();
titleList.add("七里香");
titleList.add("东风破");
titleList.add("发如雪");
titleList.add("烟花易冷");
contentList.add("窗外的麻雀,在电线杆上多嘴");
contentList.add("一盏离愁孤,单伫立在窗口");
contentList.add("狼牙月,伊人憔悴,我举杯,饮尽了风雪");
contentList.add("繁华声遁入空门,折煞了庶人");
vmLayout.setData(titleList, contentList);
vmLayout.startRun();
vmLayout.setOnItemClick(new VerticalMarqueeLayout.ItemClick() {
@Override
public void onItemClick(int position) {
Toast.makeText(VerticalMarqueeActivity.this, titleList.get(position) + "", Toast.LENGTH_SHORT).show();
}
});
}
demo地址,包含多个demo,自取自己需要的
有需要自取