说到跑马灯,android TextView控件已经有这样的属性设置,唯一要注意的就是:
- TextView要设置单行显示:android:singleLine=”true”
- 使用跑马灯属性:android:ellipsize=”marquee”
- 最重要的,也是很多人发现为啥跑马灯不起作用,在设置了上面2个属性之后,其实就是忘记了要想它跑起来还得让TextView获得焦点才行。可以在代码里设置TextView.requestFocus(),会有意想不到的收获呢;
主题有点偏了,上面的跑马灯属于水平动画效果,今天我想实现的是垂直(ps. PM 想要这种效果,我们这些苦力不得不抓耳挠腮啊),网上也有很多大神实现了这样的效果,主要就是运用动画(平移动画),也可以用属性动画来搞,偶偷懒就简单用水平动画就行了,再加了点事件监听。好了,废话到此为止,上代码。
1.跑马灯布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:background="#fff">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingRight="5dp"
android:paddingTop="3dp"
android:paddingBottom="3dp">
<TextView
android:id="@+id/marqueelayout_notice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="垂直跑马灯"
android:textColor="#000"
android:textSize="@dimen/nomarl_font"/>
</LinearLayout>
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#6eb92d"/>
<FrameLayout
android:id="@+id/marqueelayout_layout"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="15dp"
android:background="#fff">
<LinearLayout
android:id="@+id/marqueelayout_two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:background="#fff">
<TextView
android:id="@+id/marqueelayout_two_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是标题"
android:textColor="#000"
android:textSize="@dimen/alitsamll_font"
android:singleLine="true"
android:ellipsize="end"/>
<TextView
android:id="@+id/marqueelayout_two_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是副标题"
android:textColor="#505050"
android:textSize="@dimen/samll_font"
android:singleLine="true"
android:ellipsize="end"/>
</LinearLayout>
<LinearLayout
android:id="@+id/marqueelayout_one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:background="#fff">
<TextView
android:id="@+id/marqueelayout_one_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是标题"
android:textColor="#000"
android:textSize="@dimen/alitsamll_font"
android:singleLine="true"
android:ellipsize="end"/>
<TextView
android:id="@+id/marqueelayout_one_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是副标题"
android:textColor="#505050"
android:textSize="@dimen/samll_font"
android:singleLine="true"
android:ellipsize="end"/>
</LinearLayout>
</FrameLayout>
</LinearLayout>
2.垂直跑马灯实现类
import java.util.ArrayList;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MyMarqueeLayout extends LinearLayout implements OnClickListener, AnimationListener{
private Context mContext;
private FrameLayout mainLayout;
private LinearLayout oneLayout, twoLayout;
private TextView oneTitleTV, oneContentTV, twoTitleTV, twoContentTV;
private ArrayList<MarqueeBean> arrayList = new ArrayList<MarqueeBean>();
private int index;
private int h;
private onClickPositionListener positionListener;
public MyMarqueeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.mContext = context;
initView();
}
public MyMarqueeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
initView();
}
public MyMarqueeLayout(Context context) {
super(context);
this.mContext = context;
initView();
}
private void initView(){
View view = LayoutInflater.from(mContext).inflate(R.layout.base_marqueelayout_item, null,false);
view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
this.addView(view);//把view添加到我们的MyMarqueeLayout里并设置大小
measureView(view);//计算跑马灯显示区的大小
h = view.getMeasuredHeight();
mainLayout = (FrameLayout)view.findViewById(R.id.marqueelayout_layout);
oneLayout = (LinearLayout)view.findViewById(R.id.marqueelayout_one);
twoLayout = (LinearLayout)view.findViewById(R.id.marqueelayout_two);
oneTitleTV = (TextView)view.findViewById(R.id.marqueelayout_one_title);
oneContentTV = (TextView)view.findViewById(R.id.marqueelayout_one_content);
twoTitleTV = (TextView)view.findViewById(R.id.marqueelayout_two_title);
twoContentTV = (TextView)view.findViewById(R.id.marqueelayout_two_content);
if(arrayList.size() >= 2){//初始化文本
oneTitleTV.setText(arrayList.get(0).getTitle());
oneContentTV.setText(arrayList.get(0).getContent());
twoTitleTV.setText(arrayList.get(1).getTitle());
twoContentTV.setText(arrayList.get(1).getContent());
}
mainLayout.setOnClickListener(this);//给内容显示区添加点击事件
}
/**
* 计算子view 大小(注意这个方面只能在LinearLayout下)
* @param childView
*/
private void measureView(View childView) {
LayoutParams p = (LayoutParams) childView.getLayoutParams();
if (p == null) {
p = (LayoutParams) new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
int height = p.height;
int childHeightSpec;
if (height > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(height,
MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED);
}
childView.measure(childWidthSpec, childHeightSpec);
}
/**
* 动画效果
* @param firstLayout
* @param seconedLayout
*/
private void startAnim(LinearLayout firstLayout, LinearLayout seconedLayout){
TranslateAnimation t1 = new TranslateAnimation(0, 0, 0, -h);// 水平动画
t1.setDuration(3000);
t1.setFillAfter(true);
t1.setStartOffset(1000);// 延迟1秒
TranslateAnimation t2 = new TranslateAnimation(0, 0, h, 0);// 水平动画
t2.setDuration(3000);
t2.setStartOffset(1000);
t2.setFillAfter(true);
firstLayout.startAnimation(t1);
seconedLayout.startAnimation(t2);
t1.setAnimationListener(this);//添加动画监听
}
/**
* 填充数据
* @param list
*/
public void setList(ArrayList<MarqueeBean> list){
this.arrayList = list;
if(arrayList.size() == 1){
oneTitleTV.setText(arrayList.get(0).getTitle());
oneContentTV.setText(arrayList.get(0).getContent());
}
if(arrayList.size() == 2){
oneTitleTV.setText(arrayList.get(0).getTitle());
oneContentTV.setText(arrayList.get(0).getContent());
twoTitleTV.setText(arrayList.get(1).getTitle());
twoContentTV.setText(arrayList.get(1).getContent());
}
}
/**
* 开始
*/
public void start(){
if(arrayList.size() > 1){ //只有内容条数大于1的时候 才实现跑马灯动画效果
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
startAnim(oneLayout, twoLayout);
}
}, 4000);
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.marqueelayout_layout:
//根据计数器index 得到点击的位置
if(positionListener != null){
if(index < arrayList.size()){
positionListener.onClick(index);
}else{
int position = (index)%arrayList.size();
positionListener.onClick(position);
}
}
break;
default:
break;
}
}
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
int position = (index+2)%arrayList.size();//找到下一个显示内容
if(index%2 == 0){ // 根据计数器 动态填充TextView 内容
oneTitleTV.setText(arrayList.get(position).getTitle());
oneContentTV.setText(arrayList.get(position).getContent());
startAnim(twoLayout, oneLayout);
}else{
twoTitleTV.setText(arrayList.get(position).getTitle());
twoContentTV.setText(arrayList.get(position).getContent());
startAnim(oneLayout, twoLayout);
}
index ++;
}
@Override
public void onAnimationRepeat(Animation animation) {
}
/**
* 走马灯 点击位置 接口类
* @author YC
*/
public interface onClickPositionListener {
void onClick(int position);
}
public void setListener(onClickPositionListener listener){
this.positionListener = listener;
}
}
ps. MarqueeBean 只是一个跑马灯的内容存放Bean
3.MyMarqueeLayout 具体使用
final ArrayList<MarqueeBean> arrayList = new ArrayList<MarqueeBean>();
MyMarqueeLayout marqueeLayout = (MyMarqueeLayout)headview.findViewById(R.id.main_buyfood_marquee);
MarqueeBean bean1 = new MarqueeBean();
bean1.setTitle("标题1");
bean1.setContent("副标题1");
arrayList.add(bean1);
MarqueeBean bean2 = new MarqueeBean();
bean2.setTitle("标题2");
bean2.setContent("副标题2");
arrayList.add(bean2);
MarqueeBean bean3 = new MarqueeBean();
bean3.setTitle("标题3");
bean3.setContent("副标题3");
arrayList.add(bean3);
marqueeLayout.setList(arrayList);
marqueeLayout.start();
marqueeLayout.setListener(new onClickPositionListener() {
@Override
public void onClick(int position) {
Toast.makeText(getActivity(), "position:"+position +"||title:"+arrayList.get(position).getTitle(), Toast.LENGTH_SHORT).show();
}
});
4.图呢。 其实我也想要问图呢。。我只截了几张图,准备做gif的发现,太水了,还是不拿来献丑了。还是大家自己亲测吧(我自己只是亲测过了,效果很赞,不然我也不发啦)