Android 如果有多行,如何使textview在另一个textview下继续
Iam使用两个文本视图的项目填充RecyclerView,一个是标签(左文本视图),另一个包含内容(右文本视图)。当内容文本变长时,它将创建多行。现在,如果我们有更多的一行,我希望文本继续在标签下面,这是可能的吗?如果没有,如果内容textview中有多行,如何使textview垂直Android 如果有多行,如何使textview在另一个textview下继续,android,android-layout,Android,Android Layout,Iam使用两个文本视图的项目填充RecyclerView,一个是标签(左文本视图),另一个包含内容(右文本视图)。当内容文本变长时,它将创建多行。现在,如果我们有更多的一行,我希望文本继续在标签下面,这是可能的吗?如果没有,如果内容textview中有多行,如何使textview垂直 <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android=
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:textColor="#667889"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toStartOf="@+id/content"
tools:text="Eros donec ac odio tempor" />
<TextView
android:id="@+id/content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
app:layout_constraintStart_toEndOf="@+id/label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:text="Content - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." />
</android.support.constraint.ConstraintLayout>
要使用的属性是
android:ems=""
android:maxLines=""
ems表示字体大小,最大行数表示您希望在文本视图中显示多少行。
这些是您希望在XML中使用的属性。您可以使用单个文本视图来实现这一点,只需使用StringBuilder并将文本附加到生成器abs将该字符串生成器设置为文本视图
StringBuilder builder = new StringBuilder();
builder.append("Your Text1 );
builder.append("Your Text2 );
然后将其设置为textView
textView.setText(builder);
您可以执行以下操作: 这里的想法是采用约束布局 包含两个文本视图:
- tv\u固定的(从固定的角度来看,我不关心它的文本)
- tv_变量(从需要对其文本进行进一步处理的角度来看,变量)
setText(stringtext1,stringtext)
方法更改时):
- 在Ourtext的每个字符上循环,获取每个字符的宽度
(以像素为单位),递增cCharWidth
(这是计算我们文本中所有字符的宽度),然后检查cTotalCharWidth
是否大于TextView tv\u可变宽度(-padding),如果这样,我们就可以认为我们达到了一条新线(线是用<代码> CaleCurnter < /代码>计数)。cTotalCharWidth
- 作为下一步,我们需要检查计数的行数是否乘以TextView tv_variable line height
int cLineHeight=tv_variable.getLineHeight()代码>大于所有TextView电视固定线路 高度
int-tAllLineHeight=tv_fixed.getLineCount()*tv_fixed.getLineHeight()代码>,如果是这样的话,我们可以认为当前字符索引(<代码> i>代码>)是<>强> uTrime>强文本>文本索引,在其中文本视图tvii变量文本结束,tvyValueLyPrP文本开始。
公共类文本视图以不同方式{
私有最终字符串标记=textViewInDifferentWay.class.getSimpleName();
私人语境;
私人有限责任公司;
私有文本视图tv_fixed=null;
私有文本视图tv_变量=null;
私有文本视图tv_变量_plus=null;
私有字符串text=“”;
公共静态最终整数计算模式单线=0;
公共静态最终整数计算模式线总高度=1;
私有整数计算模式=计算模式线总高度;
public textViewInDifferentinWay(@NonNull Context Context,
@非空视图布局){
这(上下文、布局、计算、模式、线条、总高度);
}
public textViewInDifferentinWay(@NonNull Context Context,
@非空视图布局,
int计算模式){
this.context=上下文;
如果(calculationMode==计算模式单行||
calculationMode==计算模式线总高度){
this.calculationMode=calculationMode;
}
设置布局(上下文、布局);
}
专用void布局(上下文、视图布局){
if(ConstraintLayout的布局实例){
this.cl=(ConstraintLayout)布局;
if(this.cl.getChildCount()==2){
View child1=this.cl.getChildAt(0);
View child2=this.cl.getChildAt(1);
文本视图的if(child1实例)
&&child2实例(文本视图){
this.tv_fixed=(TextView)child1;
this.tv_变量=(TextView)child2;
this.text=this.tv_变量.getText().toString();
}
}否则{
抛出新的RuntimeException(“必须有两个子项!!”;
}
}
if(tv_fixed!=null&&tv_variable!=null){
/**
*在tv_fixed和tv_variable的底部添加一个屏障,以便始终写入
*具有最大高度的视图的底部
*/
ConstraintLayout.LayoutParams参数=新建ConstraintLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_内容,
ViewGroup.LayoutParams.WRAP_内容);
障碍=新障碍(上下文);
int bId=ViewCompat.generateViewId();
障碍物。setId(投标);
屏障。设置类型(屏障。底部);
barrier.setReferencedId(新int[]{tv_fixed.getId(),
tv_变量.getId()});
barrier.setLayoutParams(params_);
此.cl.addView(屏障);
ConstraintSet ConstraintSet=新ConstraintSet();
constraintSet_u2;.clone(this.cl);
constraintSet.connect(bId,constraintSet.START,this.cl.getId(),constraintSet.START);
constraintSet_2;.connect(bId,constraintSet.END,this.cl.getId(),constraintSet.END);
constraintSet_u2;.applyTo(this.cl);
/**
*添加一个文本视图(t
public class TextViewInADifferentWay {
private final String TAG = TextViewInADifferentWay.class.getSimpleName();
private Context context;
private ConstraintLayout cl;
private TextView tv_fixed = null;
private TextView tv_variable = null;
private TextView tv_variable_plus = null;
private String text = "";
public static final int CALCULATION_MODE_SINGLE_LINE = 0;
public static final int CALCULATION_MODE_LINES_TOTAL_HEIGHT = 1;
private int calculationMode = CALCULATION_MODE_LINES_TOTAL_HEIGHT;
public TextViewInADifferentWay(@NonNull Context context,
@NonNull View layout) {
this(context, layout, CALCULATION_MODE_LINES_TOTAL_HEIGHT);
}
public TextViewInADifferentWay(@NonNull Context context,
@NonNull View layout,
int calculationMode) {
this.context = context;
if(calculationMode == CALCULATION_MODE_SINGLE_LINE ||
calculationMode == CALCULATION_MODE_LINES_TOTAL_HEIGHT){
this.calculationMode = calculationMode;
}
setUpLayout(context, layout);
}
private void setUpLayout(Context context, View layout) {
if (layout instanceof ConstraintLayout) {
this.cl = (ConstraintLayout) layout;
if (this.cl.getChildCount() == 2) {
View child1 = this.cl.getChildAt(0);
View child2 = this.cl.getChildAt(1);
if (child1 instanceof TextView
&& child2 instanceof TextView) {
this.tv_fixed = (TextView) child1;
this.tv_variable = (TextView) child2;
this.text = this.tv_variable.getText().toString();
}
} else {
throw new RuntimeException("Must have two children!!");
}
}
if (tv_fixed != null && tv_variable != null) {
/**
* Add a barrier in the bottom of tv_fixed and tv_variable in order to always write to
* the bottom of the view with the largest height
*/
ConstraintLayout.LayoutParams params_ = new ConstraintLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
Barrier barrier = new Barrier(context);
int bId = ViewCompat.generateViewId();
barrier.setId(bId);
barrier.setType(Barrier.BOTTOM);
barrier.setReferencedIds(new int[]{tv_fixed.getId(),
tv_variable.getId()});
barrier.setLayoutParams(params_);
this.cl.addView(barrier);
ConstraintSet constraintSet_ = new ConstraintSet();
constraintSet_.clone(this.cl);
constraintSet_.connect(bId, ConstraintSet.START, this.cl.getId(), ConstraintSet.START);
constraintSet_.connect(bId, ConstraintSet.END, this.cl.getId(), ConstraintSet.END);
constraintSet_.applyTo(this.cl);
/**
* Add a TextView (tv_variable_plus)
*/
ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(0,
ViewGroup.LayoutParams.WRAP_CONTENT);
tv_variable_plus = new TextView(context);
int tId = ViewCompat.generateViewId();
tv_variable_plus.setId(tId);
//TODO: Clone as much attribute from base textView (tv_variable)
tv_variable_plus.setTextSize(convertPixelsToDp(tv_variable.getTextSize(),
context));
tv_variable_plus.setTextColor(tv_variable.getCurrentTextColor());
tv_variable_plus.setTypeface(null, Typeface.BOLD);
tv_variable_plus.setIncludeFontPadding(false);
tv_variable_plus.setLayoutParams(params);
this.cl.addView(tv_variable_plus);
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(this.cl);
constraintSet.connect(tv_variable_plus.getId(), ConstraintSet.TOP, bId, ConstraintSet.BOTTOM);
constraintSet.connect(tv_variable_plus.getId(), ConstraintSet.START, this.cl.getId(), ConstraintSet.START);
constraintSet.connect(tv_variable_plus.getId(), ConstraintSet.END, this.cl.getId(), ConstraintSet.END);
constraintSet.applyTo(this.cl);
//set Text to default text (xml based) in order to re-calculate
setText(tv_fixed.getText().toString(), text);
} else {
throw new RuntimeException("Both TextViews must be non null!!");
}
}
/**
* This method converts device specific pixels to density independent pixels.
*
* @param px A value in px (pixels) unit. Which we need to convert into db
* @param context Context to get resources and device specific display metrics
* @return A float value to represent dp equivalent to px value
*/
private static float convertPixelsToDp(float px, Context context) {
return px / ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
public void calculate() {
//TODO: Clone as much attribute from base textView (tv_variable)
tv_variable_plus.setTextSize(convertPixelsToDp(tv_variable.getTextSize(),
context));
tv_variable_plus.setTextColor(tv_variable.getCurrentTextColor());
tv_variable_plus.setTypeface(null, Typeface.BOLD);
tv_variable_plus.setIncludeFontPadding(false);
int cTotalCharWidth = 0;
int cLineCounter = 1;
int index = 0;
for (int i = 0; i < text.length(); i++) {
int cLineHeight = tv_variable.getLineHeight();
int tLineHeight = tv_fixed.getLineHeight();
int tAllLineHeight = tv_fixed.getLineCount() * tLineHeight;
String c = String.valueOf(text.charAt(i));
float cCharWidth = getStringWidth(tv_variable, c);
//Log.i(TAG, c + "-- w: " + cCharWidth);
cTotalCharWidth += cCharWidth;
if (cTotalCharWidth >= (tv_variable.getWidth() -
tv_variable.getPaddingLeft() - tv_variable.getPaddingRight())) {
//Log.i(TAG, "New Line after " + c + " (" + i + ")");
if (calculationMode == CALCULATION_MODE_LINES_TOTAL_HEIGHT) {
cTotalCharWidth = 0;
if (((2 * cLineCounter) * cLineHeight) >= (tAllLineHeight)) {
index = i;
break;
}
} else if (calculationMode == CALCULATION_MODE_SINGLE_LINE) {
if (cLineCounter == 1) {
index = i;
break;
}
}
cLineCounter += 1;
}
}
if (index != 0) {
tv_variable.setText(text.substring(0, index));
tv_variable_plus.setText(text.substring(index));
tv_variable_plus.setVisibility(View.VISIBLE);
} else {
tv_variable.setText(text);
tv_variable_plus.setText("");
tv_variable_plus.setVisibility(View.GONE);
}
}
private float getStringWidth(TextView tv, String text) {
Paint textPaint = tv.getPaint();
float sWidth = textPaint.measureText(text); // in pixels
return sWidth;
}
public TextView getTvFixed() {
return this.tv_fixed;
}
public TextView getTvVariable() {
return this.tv_variable;
}
public TextView getTvVariablePlus() {
return this.tv_variable_plus;
}
public TextViewInADifferentWay setCalculationMode(int calculationMode) {
if (calculationMode == CALCULATION_MODE_SINGLE_LINE ||
calculationMode == CALCULATION_MODE_LINES_TOTAL_HEIGHT) {
if (calculationMode != this.calculationMode) {
this.calculationMode = calculationMode;
calculate();
}
}
return TextViewInADifferentWay.this;
}
public TextViewInADifferentWay setText(String text1, String text) {
this.text = text;
tv_fixed.setText(text1);
tv_variable.setText(text);
if (tv_variable_plus != null) {
tv_variable_plus.setText("");
/**
* make sure that views are inflated before calculating
*/
final ViewTreeObserver viewTreeObserver = this.cl.getViewTreeObserver();
viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
cl.getViewTreeObserver().removeOnPreDrawListener(this);
calculate();
return true;
}
});
}
return TextViewInADifferentWay.this;
}
public String getText() {
return this.text;
}
}
public class MainActivity extends AppCompatActivity {
private final String TAG = MainActivity.class.getSimpleName();
private RecyclerView rv_before;
private RecyclerView rv_after;
private Button b;
private List<String> one = new ArrayList<>();
private List<String> two = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
one.add("Hello, how is work?");
two.add("Hello, everything is fine, thank you for asking.");
one.add("?");
two.add("How are you today?");
one.add("I not feeling well!");
two.add("Are you sick, you seem extremely tired?");
one.add("I've got flu");
two.add("Go home and please stay there until you feel better. " +
"You don't want to spread your infection!");
rv_before = (RecyclerView) findViewById(R.id.rv_before);
rv_before.setHasFixedSize(true);
LinearLayoutManager linearLayoutManagerB = new LinearLayoutManager(MainActivity.this);
rv_before.setLayoutManager(linearLayoutManagerB);
rv_after = (RecyclerView) findViewById(R.id.rv_after);
rv_after.setHasFixedSize(true);
LinearLayoutManager linearLayoutManagerA = new LinearLayoutManager(MainActivity.this);
rv_after.setLayoutManager(linearLayoutManagerA);
CustomRecyclerViewAdapter customRecyclerViewAdapterB = new CustomRecyclerViewAdapter(MainActivity.this, true, one, two);
rv_before.setAdapter(customRecyclerViewAdapterB);
CustomRecyclerViewAdapter customRecyclerViewAdapterA = new CustomRecyclerViewAdapter(MainActivity.this, false, one, two);
rv_after.setAdapter(customRecyclerViewAdapterA);
b = (Button) findViewById(R.id.b);
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
List<String> fixed = new ArrayList<>();
List<String> variable = new ArrayList<>();
for (int i = 0; i < one.size(); i++) {
int oneI = new Random().nextInt(one.size());
fixed.add(one.get(oneI));
variable.add(two.get(oneI));
}
customRecyclerViewAdapterB.changeText(fixed, variable);
customRecyclerViewAdapterA.changeText(fixed, variable);
}
});
}
private class CustomRecyclerViewAdapter extends RecyclerView.Adapter<CustomRecyclerViewAdapter.CustomViewHolder> {
private final Context context;
private List<String> fixed;
private List<String> variable;
private final boolean before;
public CustomRecyclerViewAdapter(Context context, boolean before,
List<String> fixed, List<String> variable) {
super();
this.context = context;
this.before = before;
this.fixed = fixed;
this.variable = variable;
}
@NonNull
@Override
public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View layout = LayoutInflater.from(context).inflate(R.layout.recycler_view_item, parent, false);
return new CustomViewHolder(layout);
}
@Override
public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) {
if(!before) { // after
holder.textViewInADifferentWay.setText(fixed.get(position), variable.get(position));
}else{ // before
TextView tv_fixed = (TextView) holder.text_view_in_a_different_way.findViewById(R.id.tv_fixed);
TextView tv_variable = (TextView) holder.text_view_in_a_different_way.findViewById(R.id.tv_variable);
tv_fixed.setText(fixed.get(position));
tv_variable.setText(variable.get(position));
}
holder.tv.setText("Item " + position + " top");
holder.tv1.setText("Item " + position + " bottom");
}
@Override
public int getItemCount() {
return fixed.size();
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
private TextViewInADifferentWay textViewInADifferentWay;
private final View text_view_in_a_different_way;
private final TextView tv;
private final TextView tv1;
public CustomViewHolder(@NonNull View itemView) {
super(itemView);
text_view_in_a_different_way = (View)
itemView.findViewById(R.id.text_view_in_a_different_way);
if(!before) { // after
textViewInADifferentWay = new TextViewInADifferentWay(context,
text_view_in_a_different_way);
}
tv = (TextView) itemView.findViewById(R.id.tv);
tv1 = (TextView) itemView.findViewById(R.id.tv1);
}
}
public void changeText(List<String> fixed, List<String> variable) {
this.fixed = fixed;
this.variable = variable;
this.notifyDataSetChanged();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/rl"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Change Data Set"
android:id="@+id/b"
android:textAllCaps="false"
android:layout_alignParentTop="true"
android:layout_marginTop="10dp">
</Button>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/b"
android:orientation="vertical"
android:layout_marginTop="10dp"
android:weightSum="100">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="26.5"
android:id="@+id/rv_before">
</androidx.recyclerview.widget.RecyclerView>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="47"
android:text="Divider (before - after)"
android:gravity="center"
android:textColor="@android:color/white"
android:background="@color/colorAccent">
</TextView>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="26.5"
android:id="@+id/rv_after">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- other stuff -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:id="@+id/tv"
android:gravity="center"
android:textColor="@android:color/white"
android:background="@color/colorPrimary"
android:text="Item">
</TextView>
<!-- other stuff -->
<include
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/text_view_in_a_different_way"
layout="@layout/text_view_in_a_different_way">
</include>
<!-- other stuff -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:id="@+id/tv1"
android:gravity="center"
android:textColor="@android:color/white"
android:background="@color/colorPrimaryDark"
android:text="Item">
</TextView>
<!-- other stuff -->
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cl"
android:padding="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_fixed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="15sp"
android:textStyle="bold"
android:ellipsize="marquee"
android:gravity="center_vertical"
android:includeFontPadding="false"
android:background="@color/colorPrimary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toStartOf="@id/tv_variable"
android:text="Hello World World Hello" />
<TextView
android:id="@+id/tv_variable"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:gravity="center_vertical"
android:includeFontPadding="false"
android:textColor="@color/colorAccent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tv_fixed"
android:text="Hello World Hello World Hello World" />
</androidx.constraintlayout.widget.ConstraintLayout>