I wanted to post an image to describe this problem, but apparently I don't have enough of a reputation with stackoverflow yet, so I'm going to try to describe what I am trying to accomplish.
I have a TableLayout with 5 columns. They consist of a company name, a job number, a last name, a graphic vertical divider, and a right arrow button. I would like the divider and right arrow button to be right justified against the right side of the screen. I would like column 2 (the job number) to expand large enough to hold the entire number without wrapping. I would like columns 1 (company name) and 3 (last name) to fill in the rest of the table and use ellipses if they are too big (no text wrapping). My table is built programmatically.
Currently, whenever the company name gets too long, the divider and right arrow get pushed off the right side of the screen.
Here is my layout.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView android:id="#+id/searchResultsFoundTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16dp"
android:text="#string/searchResultsLabel"/>
<ScrollView android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TableLayout android:id="#+id/searchResultsTableLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="10dp"
android:stretchColumns="1"
android:shrinkColumns="0,2" />
</ScrollView>
</LinearLayout>
Here is my code to build the table:
TableLayout table = (TableLayout)findViewById(R.id.searchResultsTableLayout);
for (JobBase job : jobList) {
TableRow row = new TableRow(this);
row.setLayoutParams(new TableRow.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
row.setPadding(5, 10, 5, 20);
table.addView(row);
TextView customerNameTextView = new TextView(this);
customerNameTextView.setText(job.getCustomerName());
customerNameTextView.setEllipsize(TextUtils.TruncateAt.END);
customerNameTextView.setTextSize(FONT_SIZE);
customerNameTextView.setPadding(10, 5, 10, 0);
row.addView(customerNameTextView);
TextView jobNumberTextView = new TextView(this);
jobNumberTextView.setText(job.getJobNumber());
jobNumberTextView.setTextSize(FONT_SIZE);
jobNumberTextView.setPadding(10, 5, 10, 0);
row.addView(jobNumberTextView);
TextView crewLeaderTextView = new TextView(this);
crewLeaderTextView.setText(job.getCrewLeader().getLastName());
crewLeaderTextView.setEllipsize(TextUtils.TruncateAt.END);
crewLeaderTextView.setTextSize(FONT_SIZE);
crewLeaderTextView.setPadding(10, 5, 10, 0);
row.addView(crewLeaderTextView);
ImageView dividerImageView = new ImageView(this);
dividerImageView.setImageDrawable(getResources().getDrawable(R.drawable.btn_med_hl_div_white));
dividerImageView.setPadding(10, 10, 10, 0);
row.addView(dividerImageView);
Button rightArrowButton = new Button(this);
rightArrowButton.setBackgroundDrawable(getResources().getDrawable(R.drawable.right_arrow_button));
rightArrowButton.setPadding(10, 0, 10, 0);
rightArrowButton.setOnClickListener(new RowSelectedAction(row));
row.addView(rightArrowButton);
row.setOnClickListener(new RowSelectedAction(row));
}
Any help would be much appreciated.
I was able to fix this by adding a weight through LayoutParams to the first column:
TextView customerNameTextView = new TextView(this);
customerNameTextView.setText(job.getCustomerName());
// --- Added this statement
customerNameTextView.setLayoutParams(new TableRow.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
// ---
customerNameTextView.setEllipsize(TextUtils.TruncateAt.END);
customerNameTextView.setTextSize(FONT_SIZE);
customerNameTextView.setPadding(10, 5, 10, 0);
row.addView(customerNameTextView);
The first column now expands and contracts and the divider and button are always right justified. Sometimes the customer name is ellipsized and other times the name wraps, but that doesn't matter to me as long as the column sizes correctly.
Related
I have an Android app, inside I have 3 TextViews in a vertical LinearLayout. I want to blur parts of the TextViews by a String array containing the words that should be blurred. The TextViews looks like this.
In this example, I want to blur all the occurrences of the words "than" and "third".
I currently blur the text using a BlurMaskFilter like in this answer. However, it blurs the whole text in the TextView, and I want to blur specific words only.
My solution was replacing the 3 TextViews by 3 horizontal LinearLayouts and loop through the text of the TextViews, when reaching a word that needs to be blurred, split the TextView to three TextViews: start, blurred part, end. In our example, it will be "this is the", "third"(blurred), "textview" for the third TextView.
The problem I get can be seen here:
So as you can see, when the text reaches more than one row, the second line won't start from the start of the screen, as it is a LinearLayout and the view before it takes some space. What I want to achieve is being able to cut a TextView in the middle of a line, even if it is a multiline TextView, add another TextView right next to it and blur it, and add the continuation of the text afterward, and it'll start the next line from the beginning. I don't know any layout type that will fit these needs, nor a way of achieving it in a different way.
My current code to achieve the state shown in the last picture:
Activity --> create the texts, and append them to the layouts:
LinearLayout linear0 = findViewById(R.id.testlinear0);
LinearLayout linear1 = findViewById(R.id.testlinear1);
LinearLayout linear2 = findViewById(R.id.testlinear2);
TextView firstTextView = new TextView(this);
firstTextView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
setHtmlText(firstTextView, "adsada");
firstTextView.setTextAppearance(this, R.style.WikiTextViewStyle);
TextView aaa = new TextView(this);
aaa.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
setHtmlText(aaa, HelperClass.levelsContent.get(levelName)[0]);
aaa.setTextAppearance(this, R.style.WikiTextViewStyle);
TextView secondTextView = new TextView(this);
secondTextView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
setHtmlText(secondTextView, HelperClass.levelsContent.get(levelName)[1]);
secondTextView.setTextAppearance(this, R.style.WikiTextViewStyle);
TextView thirdTextView = new TextView(this);
thirdTextView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
setHtmlText(thirdTextView, HelperClass.levelsContent.get(levelName)[2]);
thirdTextView.setTextAppearance(this, R.style.WikiTextViewStyle);
thirdTextView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
float radius = thirdTextView.getTextSize() / 3;
BlurMaskFilter filter = new BlurMaskFilter(radius, BlurMaskFilter.Blur.NORMAL);
thirdTextView.getPaint().setMaskFilter(filter);
linear0.addView(firstTextView);
linear0.addView(aaa);
linear1.addView(secondTextView);
linear2.addView(thirdTextView);
layout -->
<LinearLayout
android:id="#+id/imgLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:id="#+id/testlinear0"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="#+id/testlinear1"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="#+id/testlinear2"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
perhaps use a SpannableString and mark the portion of text you want to be blurred using a MaskFilterSpan? For example:
SpannableString string = new SpannableString("Text with blur mask");
MaskFilter blurMask = new BlurMaskFilter(5f, BlurMaskFilter.Blur.NORMAL);
string.setSpan(new MaskFilterSpan(blurMask), 10, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(string);
I am creating a TableLayout to populate data dynamically. The problem I am facing here is that rows are not fitting horizontally into the screen.
This is my desired View,
\-----------------------------------------------------\
\| Student Name | Q1 | Q2 | Q3 | Total | % |\
\-----------------------------------------------------\
But the problem is,as Student Name is quite a large row (in width), the other rows are not fitting into the screen,
they are appearing like as shown below, from Q4 onwards all the rows are not fitting into the screen.
\------------------------------------\----------------
\| Student Name | Q1 | Q2 | Q3 \| Total | % |
\------------------------------------\----------------
This is the code I have used to create this view dynamically
students_table.xml
<ScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scrollbars="none">
<TableLayout
android:id="#+id/maintable"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</ScrollView>
QuestionPaperChecking.java
/** Table Row - Header */
trHeader = new TableRow(mContext);
trHeader.setLayoutParams(new TableLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
/* Student name */
TextView tvStudentName = new TextView(mContext);
tvStudentName.setText("Student Name");
tvStudentName.setTextColor(Color.WHITE);
tvStudentName.setGravity(Gravity.CENTER_VERTICAL);
tvStudentName.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
tvStudentName.setBackgroundColor(getColor(mContext, R.color.background_blue_light));
tvStudentName.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
tvStudentName.setPadding(10, 10, 10, 10);
trHeader.addView(tvStudentName);
/* Question 1 */
TextView tvQ1 = new TextView(mContext);
tvQ1.setText("Q1");
tvQ1.setTextColor(Color.WHITE);
tvQ1.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
tvQ1.setBackgroundColor(getColor(mContext, R.color.background_blue_light));
tvQ1.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
tvQ1.setPadding(10, 10, 10, 10);
tvQ1.setGravity(Gravity.CENTER_VERTICAL);
trHeader.addView(tvQ1);
//Similarly I have created all other rows
// Add the TableRow Header to the TableLayout
tblBattingSide.addView(trHeader, new TableLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
Note: stretchColumns & shrinkColumns didnot work
I assume that you'd want to the text on the student's name to wrap to the next line.
The first thing to fix is the layout_width. Set the layout_width value of the ScrollView to match_parent/fill_parent. Do the same for the header TableRow (trHeader) as well as for each row you had to the table. Just to be clear, layout_width on the TableLayout itself should remain match_parent/fill_parent.
What this does is make sure all these views fit width-wise into the parents. This will still not completely solve the problem since the views in the rows still "push" the columns beyond the width of the table's container.
The second step is to set shrinkColumns on the TableLayout to "1". This will shrink the first column as much as possible until the table fits in the screen (or its container), and the text will wrap. Alternatively, you can set it to "*" if you want all columns to shrink.
I'm got a stretched table and I want my checkbox to appear central also within the table row. On the textView I've called:
myTextView.setGravity(Gravity.CENTER);
And I've also tried setting it as a table parameter:
This is my XML that sets up the table:
<TableLayout
android:id="#+id/info"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/linearLayout1"
android:layout_margin="6dp"
android:stretchColumns="0,1,2,3,4" >
<TableRow
android:id="#+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:background="#drawable/roundedheader" >
And this is the code I'm calling as I create each row:
//set table margin
TableLayout.LayoutParams tableRowParams= new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
int leftMargin=0,rightMargin=0,bottomMargin=0;
int topMargin=5;
tableRowParams.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
tableRowParams.gravity = Gravity.CENTER;
row.setLayoutParams(tableRowParams);
// add the TableRow to the TableLayout
table.addView(row);
However the same command doesn't have the desired effect on the checkbox. Does any know what the difference is and what I need to do. The checkbox isn't within any other layout its just in the table row.
I recommend you before start working with TableLayout to check these links:
http://developer.android.com/reference/android/widget/TableLayout.html
http://developer.android.com/reference/android/widget/TableRow.html
http://developer.android.com/reference/android/widget/TableRow.LayoutParams.html
Also there is bunch of examples how to work with TableLayout in API Demos from Android SDK.
Assuming your layout android:stretchColumns="0,1,2,3,4" you will have at least 5 columns, but from the code snippet I can't assume how many views are added to row. You will need to specify TableRow.LayoutParams android:layout_span if there are less view elements then columns and you want to use that free space. So assuming that you have only one CheckBox in a row and only 5 columns you will need to do next:
TableRow.LayoutParams rowParams = new TableRow.LayoutParams();
rowParams.gravity = Gravity.CENTER;
rowParams.span = 5;
checkBox.setLayoutParams(rowParams);
Also I recommend you to use xml layouts instead of creating them from the code. If you can't stick with xml layouts then at least create them using xml editor, so you will have good start point for creating them from the code.
I am using linear layout with 2 textviews, 4 buttons, 1 seekbar,1 image view. If I am place those textviews,buttons, etc. in a linear layout the alignment is fine in android phone. While I am running the same code in android tablet, alignment is not proper. Why this alignment is not proper in tablet.? I have created the textviews,buttons etc by java code. Even I am specifying the two text views horizontally by settings the left margin of the second text view by devicewidth/2 having the difference in android phone and tablet. I need to align like the below.
TextView1 TextView2
Button1 Button2 Button3 Button4 SeekBar ImageView
Here is my code.
LinearLayout.LayoutParams textViewParams1 = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
textViewLayout.setOrientation(LinearLayout.HORIZONTAL);
TextView TextView1=new TextView(this);
TextView1.setText("Text1");
textViewParams1.gravity=Gravity.CENTER;
textViewParams1.setMargins(60, 20, 40, 10);
textViewLayout.addView(chooseColorTextView, textViewParams1);
LinearLayout.LayoutParams textViewParams2 = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
TextView TextView2=new TextView(this);
TextView2.setText("Text2");
int width=getWindowManager().getDefaultDisplay().getWidth();
textViewParams2.gravity=Gravity.CENTER;
textViewParams2.setMargins((width/2), 20, 40, 10);
textViewLayout.addView(strokeWidthTextView, textViewParams2);
parentlinearLayout.addView(textViewLayout, textViewLayoutParams);
In the next linear layout, I have added the 4 buttons,seekbar and image view. But facing problems in alignment.
I advise to create complex layout that must be rendered on different screen sizes in XML rather than programmatically, so you can have two different main.xml in res/layout and in res/layout-large and the system would pick up the correct one depending on screen size.
Use layout_weight and weightSum in XML:
<LinearLayout android:weightSum="1" android:layout_width="match_parent" android:layout_height="wrap_content">
<!-- First column -->
<LinearLayout android:layout_weight=".5" android:layout_width="0dp" android:layout_height="wrap_content"> ... </LinearLayout>
<!-- Second column -->
<LinearLayout android:layout_weight=".5" android:layout_width="0dp" android:layout_height="wrap_content"> ... </LinearLayout>
</LinearLayout>
This will produce a dynamically resizing 2 column layout. If you want the divide shorter or longer, change .5 to .3 and .7 for a 30/70% split etc.
Please read more about wrap_content and other android controls. Also read about dpi of tablets. Due to resolution appearance changes.
Why don't you use a TableLayout ? its the one you need to manage cells alignement:
All that you need is in the span attribute to make cells use multiple columns.
TableLayout myLayout = new TableLayout(myContext);
TableRow row1 = new TableRow(myContext);
TableRow.LayoutParams layouparams1 = new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT,TableRow.LayoutParams.WRAP_CONTENT);
layouparams1.span = 4;
row1.setLayoutParams = layouparams1 ;
TableRow.LayoutParams layouparams2 = new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT,TableRow.LayoutParams.WRAP_CONTENT);
layouparams2.span = 2;
TableRow row2 = new TableRow(myContext);
row2.setLayoutParams = layouparams2 ;
//then create and add your childs to each row :
...
row1.addView(text1);
row1.addView(text1);
row1.addView(button1);
row1.addView(button2);
row1.addView(button3);
row1.addView(button4);
row1.addView(seekbar);
row1.addView(imageView);
myLayout.addView(row1);
myLayout.addView(row2);
also consider adding layout_weight on children to manage the space they left to each other.
I am using Tablerow+TextView to make a simple view for blog posts and their replies. In each TableRow I put a TextView in. Now I have two issues:
The text which is longer than the screen won't automatically wrap up to be multi-line. Is it by design of TableRow? I've already set tr_content.setSingleLine(false); [update] This has been addressed, I think I should change Fill_parent to be Wrap_content in textView.tr_author_time.setLayoutParams(new LayoutParams(
LayoutParams.**WRAP_CONTENT**,
LayoutParams.WRAP_CONTENT));
The Table won't scroll like ListView. My rows are more than the screen size. I expect the table could be scrolled down for viewing just like ListView. Is that possible?
Here is my code:
TableLayout tl = (TableLayout) findViewById(R.id.article_content_table);
TextView tr_title = new TextView(this);
TextView tr_author_time = new TextView(this);
TextView tr_content = new TextView(this);
TableRow tr = new TableRow(this);
for(int i = 0; i < BlogPost.size(); i++){
try{
// add the author, time
tr = new TableRow(this);
/////////////////add author+time row
BlogPost article = mBlogPost.get(i);
tr_author_time = new TextView(this);
tr_author_time.setText(article.author+"("+
article.post_time+")");
tr_author_time.setTextColor(getResources().getColor(R.color.black));
tr_author_time.setGravity(0x03);
tr_author_time.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
tr.addView(tr_author_time);
tl.addView(tr,new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
////////////////////// then add content row
tr = new TableRow(this);
tr_content = new TextView(this);
tr_content.setText(article.content);
tr_content.setSingleLine(false);
tr_content.setGravity(0x03);
tr_content.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
tr.addView(tr_content);
tr.setBackgroundResource(R.color.white);
tl.addView(tr,new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
}
A more appropriate thing to do for wrapping items would have been to add android:shrinkColumns="*" or android:shrinkColumns="1" to the TableLayout, this would probably have fixed the wrapping issue.
For Details
This isn't really a complete answer, but it really seems like you're doing this the hard way.
Instead of constructing your TableRows manually, you should set them up in xml like this:
tablerow.xml:
<TableRow xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:id="#+id/content"
android:singleLine="false"
android:textAppearance="#style/someappearance" />
</TableRow>
Prior to your loop, get a reference to a LayoutInflater:
LayoutInflater inflater = getLayoutInflater();
Then, inside your loop, create an instance of tablerow using the LayoutInflater:
TableRow row = (TableRow)inflater.inflate(R.layout.tablerow, tl, false);
TextView content = (TextView)row.findViewById(R.id.content);
content.setText("this is the content");
tl.addView(row);
This will allow you to set your layout, appearance, layout params in xml making it much easier to read and debug.
For the scrolling problem, you'll need to add your TableLayout to a ScrollView. Something like this in your xml:
<ScrollView>
<TableLayout android:id="#+id/arcitle_content_table" />
</ScrollView>
To wrap text in table rows:
By default, TableLayout rows fit the width of their content, no matter it goes over the screen bounds. To get the wider-than-screen text cells to wrap to multi-line, use android:shrinkColumns attribute on TableLayout.
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="*" />
android:shrinkColumns is zero-based index of the columns to shrink. It removes unnecessary extra space from a column and shrinks it :
android:shrinkColumns="*" shrinks all columns
android:shrinkColumns="0" shrinks first column
android:shrinkColumns="1,2" shrinks the second and third columns
android:stretchColumns does the opposite. It stretches a column to the maximum available width.
Both "shrink" and "stretch" consider all rows of the table to compute space.
To scroll down a TableLayout:
If your TableLayout is higher than the screen, move it in a ScrollView.