您的位置:首页 > 移动开发 > Android开发

Android可以纵向滚动的textView

2016-03-21 12:51 447 查看
在项目上遇到这么一个需求

1、一段文字,最多显示两行,点击某个单词进入A页面,点击另一个单词进入B页面,

2、如果句子太长的话,让这个textView可以上下滚动,但textView的高度始终是原来两行的高度,不能增高,并且单词的点击事件不能消失,

3、由于这个textView是套在recyclerVIew中的,在滚动textView的时候还不能让recyclerView滚动。而且为了性能问题,不能采用scrollView内嵌textView的方式,所以采用了下面的方法。

思路比较简单,实现textView中具体某个单词的点击事件只需要用textView.append(一个可点击的继承spannable的类就好)

首先这个textView的布局

<TextView
android:id="@+id/ctv_card_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_weight="1"
android:maxLines="2"
android:textSize="15sp"
android:text="John Doe uploaded 4 photos"
android:textColor="#505256"
/>


注意这里的maxLines=2也就是说最多显示两行,这里这么设置主要为了后面拿到这个textView高度设置的

下面就是初始化这个TextView,在代码里设置可以点击的单词,并且执行textView.setMovementMethod(),让TextView可以纵向滚动

public static void initCardHeader(final Activity activity, final TextView textView, String userName, String middleText, String restaurantName, final long userId , final long restaurantId , TextView ctv_reviewPhoto_count, long reviewCount , int photoCount){
if(textView==null||activity==null)return;
textView.setText("");//清空textView
SpannableString userNameSpan = new SpannableString(userName);
userNameSpan.setSpan(new ClickableSpan() {
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(0xFF505256);
ds.setAntiAlias(true);//抗锯齿
ds.setUnderlineText(false);
ds.setFakeBoldText(true);//设置粗体
}
@Override
public void onClick(View widget) {//在这里复写点击事件
JLogUtils.i("Alex","点击了用户名,用户id是"+userId);
if(QravedApplication.getAppConfiguration().getUserId()!=userId)return;
JLogUtils.i("Alex","准备跳转到myQraved");
if(activity instanceof HomeActivity)((HomeActivity)activity).switchFragment(HomeActivity.FRAGMENT_TYPE_HOME_HOME, HomeActivity.FRAGMENT_TYPE_HOME_MYPROFILE_MYLIST);
}
}, 0, userNameSpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.append(userNameSpan);
if(activity instanceof HomeActivity || activity instanceof JournalCommentsActivity) {
textView.append(middleText);//添加中间部分

SpannableString restaurantSpan = new SpannableString(restaurantName);
restaurantSpan.setSpan(new ClickableSpan() {
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(0xFF505256);
ds.setAntiAlias(true);//抗锯齿
ds.setUnderlineText(false);
ds.setFakeBoldText(true);//设置粗体
}

@Override
public void onClick(View widget) {//在这里复写点击事件
JLogUtils.i("Alex", "点击了餐馆名字,餐馆id是" + restaurantId);
Intent intent = new Intent();
intent.putExtra("restaurantId", String.valueOf(restaurantId));
intent.setClass(activity, RestaurantDetailActivity.class);
activity.startActivity(intent);
activity.overridePendingTransition(R.anim.enter_righttoleft, R.anim.exit_righttoleft);
}
}, 0, restaurantSpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.append(restaurantSpan);
}
textView.setMovementMethod(AlxLinkMovementMethod.getInstance());//让textView可以纵向滚动,里面这个类在本文有源码
ctv_reviewPhoto_count.setText(reviewCount + (reviewCount > 1 ? " reviews" : " review") + " - " + photoCount + (photoCount > 1 ? " photos" :" photo"));
//让两行以上可以滚动的方法
ViewTreeObserver observer = textView.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

@Override
public void onGlobalLayout() {
// TODO Auto-generated method stub

Layout layout2 = textView.getLayout();
if(textView!=null&&layout2!=null){
int lines = layout2.getLineCount();

if(lines!=2)return;//如果不到两行,就不管了
int textViewHeight = textView.getHeight();//得到两行时候的textView的高度
textView.setMaxHeight(textViewHeight);//设置textView的最大高度为现在这样
textView.setMaxLines(Integer.MAX_VALUE);//不限制textView的行数,这样才能够滚动起来
}

}
});

}


下面是最重要的LinkMovementMethod的写法了,用了这个类就可以实现textView的纵向滚动

并且实现了在recyclerView内滚动事件不冲突,并且在滚动之后仍然保持点击事件,并且防止了点击事件的误触发

package com.imaginato.qravedconsumer.widget;

import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.LinkMovementMethod;
import android.text.method.MovementMethod;
import android.text.style.ClickableSpan;
import android.view.MotionEvent;
import android.widget.TextView;

import com.imaginato.qravedconsumer.utils.JLogUtils;

/**
* Created by Administrator on 2016/3/21.
*/
public class AlxLinkMovementMethod extends LinkMovementMethod{
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
if (widget.getLayout().getLineCount() > 1) {
JLogUtils.i("Alex", "大于一行");
boolean ret = mOnTouchEvent(widget, buffer, event);
widget.getParent().requestDisallowInterceptTouchEvent(true);//阻止父层的View截获touch事件
if(event.getAction()==MotionEvent.ACTION_UP) widget.getParent().requestDisallowInterceptTouchEvent(false);
JLogUtils.i("Alex","ret是"+ret);
return true;
} else {//小于一行
boolean ret =  super.onTouchEvent(widget, buffer, event);
JLogUtils.i("Alex", "小于一行"+ret);
return ret;
}
}
private boolean couldClick = true;//现在是否响应点击事件
private float lastY;

private boolean mOnTouchEvent(TextView widget, Spannable buffer, MotionEvent event){
int action = event.getAction();
switch (event.getAction()){
case MotionEvent.ACTION_MOVE:
if(Math.abs(event.getY()-lastY)>10)couldClick = false;//只有在发生了滚动的时候才禁止点击事件
break;
}
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();

x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();

x += widget.getScrollX();
y += widget.getScrollY();

Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);

ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);

if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
JLogUtils.i("Alex","现在up了"+couldClick);
if(couldClick)link[0].onClick(widget);
} else if (action == MotionEvent.ACTION_DOWN) {
lastY = event.getY();
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
couldClick = true;
}

return true;
} else {
Selection.removeSelection(buffer);
}
}

return super.onTouchEvent(widget, buffer, event);
}

private static AlxLinkMovementMethod hahaInstance;
public static MovementMethod getInstance() {
if (hahaInstance == null)
hahaInstance = new AlxLinkMovementMethod();

return hahaInstance;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: