I work on the application to which the user must enter information. It looks like this: goes LinearLayout(horizontal) and in it TextView then EditText then TextView . Where the user must enter information in the EditText .

The problem is that when implemented, it looks like this:

 |blabla________tatata| | tatata| 

That is, if the line does not fit, the line break comes under the 3rd TextView .

And I need it to look like this:

 |blabla________tatata| |tatata | 

That is, if the line does not fit, he would throw it to the beginning of a new line.

The second option, I used this implementation of Flow TextView but, as can be seen from the example below, it is more suitable for the picture.

enter image description here

3rd option:

I use FlowLayout, with this implementation, the entire 3rd part jumps to a new line, and I need to jump only that part that does not fit. Help pliz podfissit!

What it looks like:

enter image description here

 public class HorizontalFlowLayout extends RelativeLayout { /** * Constructor to use when creating View from code. */ public HorizontalFlowLayout(Context context) { super(context); } /** * Constructor that is called when inflating View from XML. */ public HorizontalFlowLayout(Context context, AttributeSet attrs) { super(context, attrs); } /** * Perform inflation from XML and apply a class-specific base style. */ public HorizontalFlowLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // need to call super.onMeasure(...) otherwise get some funny behaviour super.onMeasure(widthMeasureSpec, heightMeasureSpec); final int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); // increment the x position as we progress through a line int xpos = getPaddingLeft(); // increment the y position as we progress through the lines int ypos = getPaddingTop(); // the height of the current line int line_height = 0; // go through children // to work out the height required for this view // call to measure size of children not needed I think?! // getting child's measured height/width seems to work okay without it //measureChildren(widthMeasureSpec, heightMeasureSpec); View child; MarginLayoutParams childMarginLayoutParams; int childWidth, childHeight, childMarginLeft, childMarginRight, childMarginTop, childMarginBottom; for (int i = 0; i < getChildCount(); i++) { child = getChildAt(i); if (child.getVisibility() != GONE) { childWidth = child.getMeasuredWidth(); childHeight = child.getMeasuredHeight(); if (child.getLayoutParams() != null && child.getLayoutParams() instanceof MarginLayoutParams) { childMarginLayoutParams = (MarginLayoutParams)child.getLayoutParams(); childMarginLeft = childMarginLayoutParams.leftMargin; childMarginRight = childMarginLayoutParams.rightMargin; childMarginTop = childMarginLayoutParams.topMargin; childMarginBottom = childMarginLayoutParams.bottomMargin; } else { childMarginLeft = 0; childMarginRight = 0; childMarginTop = 0; childMarginBottom = 0; } if (xpos + childMarginLeft + childWidth + childMarginRight + getPaddingRight() > width) { // this child will need to go on a new line xpos = getPaddingLeft(); ypos += line_height; line_height = childMarginTop + childHeight + childMarginBottom; } else { // enough space for this child on the current line line_height = Math.max( line_height, childMarginTop + childHeight + childMarginBottom); } xpos += childMarginLeft + childWidth + childMarginRight; } } ypos += line_height + getPaddingBottom(); if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) { // set height as measured since there's no height restrictions height = ypos; } else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST && ypos < height) { // set height as measured since it's less than the maximum allowed height = ypos; } setMeasuredDimension(width, height); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // increment the x position as we progress through a line int xpos = getPaddingLeft(); // increment the y position as we progress through the lines int ypos = getPaddingTop(); // the height of the current line int line_height = 0; View child; MarginLayoutParams childMarginLayoutParams; int childWidth, childHeight, childMarginLeft, childMarginRight, childMarginTop, childMarginBottom; for (int i = 0; i < getChildCount(); i++) { child = getChildAt(i); if (child.getVisibility() != GONE) { childWidth = child.getMeasuredWidth(); childHeight = child.getMeasuredHeight(); if (child.getLayoutParams() != null && child.getLayoutParams() instanceof MarginLayoutParams) { childMarginLayoutParams = (MarginLayoutParams)child.getLayoutParams(); childMarginLeft = childMarginLayoutParams.leftMargin; childMarginRight = childMarginLayoutParams.rightMargin; childMarginTop = childMarginLayoutParams.topMargin; childMarginBottom = childMarginLayoutParams.bottomMargin; } else { childMarginLeft = 0; childMarginRight = 0; childMarginTop = 0; childMarginBottom = 0; } if (xpos + childMarginLeft + childWidth + childMarginRight + getPaddingRight() > r - l) { // this child will need to go on a new line xpos = getPaddingLeft(); ypos += line_height; line_height = childHeight + childMarginTop + childMarginBottom; } else { // enough space for this child on the current line line_height = Math.max( line_height, childMarginTop + childHeight + childMarginBottom); } child.layout( xpos + childMarginLeft, ypos + childMarginTop, xpos + childMarginLeft + childWidth, ypos + childMarginTop + childHeight); xpos += childMarginLeft + childWidth + childMarginRight; } } } } 

XML

 <com.example.nikolai.app.HorizontalFlowLayout android:id="@+id/recipientsList" android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20dp" android:text="blablabla bla"/> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20dp" android:ems="5"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20dp" android:text="tatata tatat atatat ffd"/> </com.example.nikolai.app.HorizontalFlowLayout> 
  • Try the code from here . I think it will be easier to calculate the space occupied by the first two views lying on top of the main text field and, last, to add the calculated number of spaces to the beginning of the text. With third-party solutions you will suffer - you have a very non-standard task. - Yuriy SPb 2:58 pm
  • It is hardly possible to calculate the number of gaps by dp. different screens will have different values. - Nikolai
  • My idea is as follows: calculate the indentation width in pixels, then start adding spaces in the loop and calculate their coordinates. As soon as the coordinate of the space becomes more calculated to complete the cycle. - Yuriy SPb
  • Added a third option, according to your advice, but the problem is that he throws the whole TextView, and not just the one that did not fit. - Nikolai

3 answers 3

For the sake of interest I decided to try to cope with this task. It turned out quite simple (If I correctly understood the essence of the problem).

1) I added an additional LinearLayout with vertical orientation to the markup.

 <LinearLayout android:id="@+id/addedLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="blablabla bla" android:textColor="#000000" android:textSize="20sp" /> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="5" android:textSize="20dp" /> <TextView android:id="@+id/textViewRight" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="blablabla blablablabla bla blablabla bl blablabla blablablabla blablablabla blaa" android:textColor="#000000" android:textSize="20sp" /> </LinearLayout> </LinearLayout> 

I installed IDs for this Layout and for TextView , which is located to the right of editText -a. Called them by addedLayout and textViewRight

2) Already throw off the whole sheet of code, if you redo it for yourself. I just created a naked project and wrote everything in it =) Actually, activate:

 public class MainActivity extends AppCompatActivity { private TextView textViewRight; private LinearLayout addedLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textViewRight = (TextView) findViewById(R.id.textViewRight); addedLayout = (LinearLayout) findViewById(R.id.addedLayout); } @Override public void onResume() { super.onResume(); textViewRight.post(new Runnable() { @Override public void run() { int lineCount = textViewRight.getLineCount(); if (lineCount == 1) return; String allText = textViewRight.getText().toString(); String firstLine = allText.substring(0, textViewRight.getLayout().getLineEnd(0)); textViewRight.setText(firstLine); TextView textView = new TextView(getApplicationContext()); textView.setTextColor(Color.parseColor("#000000")); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20); textView.setText(allText.substring(firstLine.length())); addedLayout.addView(textView); } }); } } 

The principle is based on the fact that we in onResume see how many lines the text occupies to the right of the input field, if there are more than 1 lines, then create a new TexView , put it into our additional layout addedLayout . We put only the first line in the right one. The rest is "cut off" and put into the newly created textView .

3) Result:

screenshot

  • Please tell me what you need to add so that the text on the new line starts with a 5dp indent? And then I have a numbering. - Nikolai
  • at LinearLayout set layout_marginLeft = "5dp" - Android Android

You need another TextView which will be located on another line.

 |text1________text2Part1| |text2Part2Part2Part2Par| |t2Part2..... | 

fill text2Part1 with a certain number of characters

you place all the rest in text2Part2

    1. Make this markup:

       <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/main_text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20dp"/> <TextView android:id="@+id/left" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20dp" android:text="blablabla bla"/> <EditText android:id="@+id/edit_text" android:layout_toRightOf="@+id/left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20dp" android:ems="5"/> </RelativeLayout> 
    2. In the code, calculate the width of the last two elements in pixels. You need to do this after drawing the screen (in onResume() )

    3. After that, in the first TextView add a space and measure the coordinate of the last character of the text in it. Repeat until the coordinate is greater than the width of n2.
    4. Now you can add text to the main TextView and it will start after the first two elements and continue on the new line immediately below them

    Here is an example of a loop that adds non-breaking spaces in a text field and calculates the coordinate of the resulting text:

     TextView tv = (TextView) findViewById(R.id.text_view); for (int i = 0; i < 10; i++) { tv.append("&nbsp"); Rect bounds = new Rect(); Paint tpaint = tv.getPaint(); tpaint.getTextBounds(tv.getText().toString(), 0, tv.getText().length(), bounds); int width = bounds.width(); Log.i(LOG, "width: " + width); } 
    • Sorry, could you write this code snippet? - Nikolai
    • See the updated answer. This code adapt to your task. - JuriySPb
    • I have one task) I got carried around with the code, and it did not work out to apply it correctly, the first TextView with EditText displayed over the second TextView . Could you give the working code in the example regarding my task, and do I also need to additionally use custom Layout ? - Nikolai
    • @Nikolai, this is the essence of my idea - to place one text field under others and fill it with spaces equal to the width of the overlapping fields .. - Yuriyi SPb
    • I understood the idea, but how can we apply it, for a list of 10 such layouts? - Nikolai