Question

I want to implement something like a product list in the receipt:
Beer ......................................... 20
Milk .......................................... 10
Cookies with jam ..................... 15
Smartphone 10GB 3GHz
1GB RAM NFC 10MPx
camera .................................. 400

Description: Check info (Beer, Milk) I think it shoud be a TextView, which I need to fill with dots.
Money (20, 10) is another TextView which shoud be aligned to the right of ViewGroup.

Any ideas how to do this? Maybe I need inherited from TextView and override onDraw() or something?
Many thank for advices!!!

Was it helpful?

Solution 2

I have the solution. Maybe it will help someone.

  1. File check_info_item.xml:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="horizontal">
    <RelativeLayout android:layout_width="match_parent"
              android:layout_height="wrap_content">
    
    <TextView android:layout_height="wrap_content"
              android:layout_width="wrap_content"
              android:id="@+id/txt_fake_value"
              android:textSize="18dp"
              android:textColor="@android:color/transparent"
              android:layout_alignParentRight="true"/>
    <example.com.CheckInfoTextView android:layout_height="wrap_content"
              android:layout_width="match_parent"
              android:id="@+id/txt_fake_info"
              android:textSize="18dp"
              android:textColor="@android:color/transparent"
              android:layout_alignParentLeft="true"
              android:layout_toLeftOf="@id/txt_fake_value"/>
    <TextView android:layout_height="wrap_content"
              android:layout_width="wrap_content"
              android:id="@+id/txt_check_info_value"
              android:text=""
              android:textSize="18dp"
              android:textColor="#000"
              android:layout_alignParentRight="true"
              android:layout_alignBottom="@id/txt_fake_info"/>
    <example.com.CheckInfoTextView
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:textSize="18dp"
            android:textColor="#000"
            android:id="@+id/txt_check_info"
            android:text=""
            android:layout_alignParentLeft="true"
            android:layout_toLeftOf="@id/txt_check_info_value"/>
    </RelativeLayout>
    </LinearLayout>
    
  2. Code to fill the info fields (in the Activity):

        View row = getLayoutInflater().inflate(R.layout.check_info_item, null);
        //Fake fields needed to align base fields in the xml file
        TextView txtFakeValue = (TextView) row.findViewById(R.id.txt_fake_value);
        txtFakeValue.setText(String.valueOf(pair.second));
    
        TextView txtFake = (TextView) row.findViewById(R.id.txt_fake_info);
        txtFake.setText(pair.first);
    
        TextView txtValue = (TextView) row.findViewById(R.id.txt_check_info_value);
        txtValue.setText(String.valueOf(pair.second));
    
        TextView txtTitle = (TextView) row.findViewById(R.id.txt_check_info);
        txtTitle.setText(pair.first);
    
  3. And the CheckInfoTextView:

    public class CheckInfoTextView extends TextView {
    
    
        public CheckInfoTextView(Context context) {
            super(context);
        }
    
        public CheckInfoTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public CheckInfoTextView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        public void onWindowFocusChanged(boolean hasWindowFocus) {
            super.onWindowFocusChanged(hasWindowFocus);
            if(!hasWindowFocus) return;
    
            int requiredDots = getRequiredDotsNumber();
            if(requiredDots == 0) {
                String text = getText().toString();
                StringBuilder result = new StringBuilder();
                result.append(text.substring(0, text.lastIndexOf(' ')));
                result.append("\n");
                result.append(text.substring(text.lastIndexOf(' ') + 1));
                setText(result.toString());
    
                requiredDots = getRequiredDotsNumber();
            }
            String dots = "";
            for (int i = 0; i < requiredDots; ++i) {
                dots += " .";
            }
            setText(getText() + dots);
        }
    
        private int getRequiredDotsNumber() {
            final int width = getWidth();
            final int lastLineWidth = (int) getLayout().getLineWidth(getLineCount() - 1);
            final int availableWidthForDots = width - lastLineWidth;
            final int widthOfOneDot = getWidthOfOneDot();
            final int widthOfTwoDotsWithSpace = getWidthOfTwoDotsWithSpace();
            final int widthOfSpace = widthOfTwoDotsWithSpace - (widthOfOneDot * 2);
            final int widthOfDotWithSpace = widthOfSpace + widthOfOneDot;
            int numberOfDots = availableWidthForDots / widthOfDotWithSpace;
            return numberOfDots;
        }
    
        private int getWidthOfTwoDotsWithSpace() {
           return getStringWidth(". .");
        }
    
        private int getWidthOfOneDot() {
           return getStringWidth(".");
        }
    
        private int getStringWidth(String text) {
            Rect dotBounds = new Rect();
            getPaint().getTextBounds(text,0,text.length(),dotBounds);
            return dotBounds.width();
        }
    }
    

OTHER TIPS

You should create THREE TextViews for each row, layed out one next to another:

  1. TextView With product name (e.g. 'beer')
  2. TextView with dots
  3. TextView with number (e.g. '20')

Then put one product in one row. The Row should be relative layout where:

  • TextView no. 1 is aligned to left edge, with width set to wrap content
  • TextView no. 3 is aligneg to right edge, with width set to wrap content
  • TextView no. 2 is toLeftOf TV no. 3 and toRightOf TV no.1 and it should be filled with big amount of dots in XML file. this will never be changed.

This will work, since the TV no.2 will have width that will shrink and will always be fitted between product name and the price. believe me :)

I've changed Serg_'s CheckinfoTextView class so that it both works in the eclipse layout editor, but also adds spaces if possible, to put the page number as close to the right side as possible. I've also changed a bit how it is used.

To accomplish:

Milk...................23
Chocolate cookies......24

set the text to 'Milk 23' and 'Chocolate cookies 24' respectively

The number of spaces is rounded to nearest rather than rounded down, so it's better to put the number a little bit over to the right rather than too much to the left

public class DotAutofillTextView extends TextView {

private int availableWidthForDots;
private int widthOfSpace;
private int widthOfDotWithSpace;

public DotAutofillTextView(Context context) {
    super(context);
}

public DotAutofillTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public DotAutofillTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    int width = getWidth() - getPaddingLeft() - getPaddingRight();
    int lastLineWidth = (int) getLayout().getLineWidth(getLineCount() - 1);
    availableWidthForDots = width - lastLineWidth;
    int widthOfOneDot = getWidthOfOneDot();
    int widthOfTwoDotsWithSpace = getWidthOfTwoDotsWithSpace();
    widthOfSpace = widthOfTwoDotsWithSpace - (widthOfOneDot * 2);
    widthOfDotWithSpace = widthOfSpace + widthOfOneDot;
    int requiredDots = getRequiredDotsNumber();
    if (requiredDots != 0) {
        int spaces = getRequiredSpacesNumber(requiredDots);
        StringBuilder result = new StringBuilder();
        String text = getText().toString();
        result.append(text.substring(0, text.lastIndexOf(' ')));
        setText(result.toString());
        StringBuilder dots = new StringBuilder();
        for (int i = 0; i < requiredDots; ++i) {
            dots.append(" .");
        }
        for (int i = 0; i < spaces; ++i) {
            dots.append(" ");
        }
        result.append(dots.toString());
        result.append(text.substring(text.lastIndexOf(' ') + 1));
        setText(result.toString());
    }
    super.onLayout(changed, left, top, right, bottom);
}

private int getRequiredSpacesNumber(int requiredDots) {
    float remain = (1f * availableWidthForDots) % (1f * widthOfDotWithSpace);
    return (int) ((remain / widthOfSpace) + 0.5f);
}

private int getRequiredDotsNumber() {
    if (getLayout() == null) {
        return 1;
    }
    int numberOfDots = availableWidthForDots / widthOfDotWithSpace;
    return numberOfDots;
}

private int getWidthOfTwoDotsWithSpace() {
    return getStringWidth(". .");
}

private int getWidthOfOneDot() {
    return getStringWidth(".");
}

private int getStringWidth(String text) {
    Rect dotBounds = new Rect();
    getPaint().getTextBounds(text, 0, text.length(), dotBounds);
    return dotBounds.width();
}

}

If '.'(dots) is your basic requirement then you can try like this..

My suggestion, Use only I TextView to fit in Beer...10 (hitch)

try like this..

    int label_len = 10;//Edit as per your requirement
     String MoneyValue = "20";
    TextView tv = (TextView)findViewById(your id);
    tv.setText("Beer");

    if(tv.getText().length() < label_len){
        for(int i = tv.getText().length(); i < label_len; i++){

           tv.setText(tv.getText()+".");
        }
    }
tv.setText(tv.getText() + MoneyValue);

This is a sample with hardcoded value, you can try to add dynamically...

Hope this helps...

enter image description hereYou can achieve this by using layout.xml only.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    
    android:layout_width="fill_parent"
    android:![enter image description here][2]layout_height="fill_parent">
<LinearLayout android:layout_width="fill_parent"
    android:layout_height="wrap_content"    
    android:weightSum="1">    
<TextView android:layout_height="wrap_content"
          android:layout_width="0dp"
          android:layout_weight="0.9"          
          android:text="Milk.................................................................................................................................." />
<TextView android:layout_height="wrap_content"
          android:layout_width="0dp"
          android:layout_weight="0.1"             
          android:text="20" />
</LinearLayout>
</LinearLayout>

This solution will work for all the device with different resolutions.

Use a relative layout:

TextView View TextView

The first set the width to wrap content, and below the text view of the previous row.
The second view, set to to right of first text view, and use a background drawable with dots that repeat horizontally. Set the width to match parent.
The last view, set to right of middle view and width to wrap content and aligned to right of parent.

I've had the same problem and found this solution using ConstraintLayout:

   <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                >

            <TextView
                android:id="@+id/item"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Phone"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                />

            <TextView
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:text="...................................................................................................."
                android:maxLines="1"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintLeft_toRightOf="@id/item"
                app:layout_constraintRight_toLeftOf="@id/price"/>

            <TextView
                android:id="@+id/price"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="end"
                android:text="100"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                />
   </androidx.constraintlayout.widget.ConstraintLayout>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top