In my app, user can add a tag in EditText. After hitting "Enter", the tag will be added to the screen. Each tag can have different lengths. User can add as many as he wants. What I want is: one TextView is added after another. When they fill one line, it will start a new row, then another row. Like below (two rows of TextViews):
"text 1","text 2","text 3","Another text"
"one","Monday"
Do I have to get the widths of the screen and every TextView and then do some calculations? Or is there a graceful way to do this?
You can use a RelativeLayout as a container and you should add TextViews as programmatically. While adding TextViews, you need to calculate screen width and each TextViews width. If last added TextView width exceeds the limit, you need to move that to next row.
You can get Screen Width like below:
public static int getScreenWidth(Context ctx) {
int width = 0;
try {
DisplayMetrics metrics = new DisplayMetrics();
WindowManager wm = (WindowManager) ctx
.getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(metrics);
width = metrics.widthPixels;
} catch (Exception e) {
e.printStackTrace();
}
return width;
}
But, there are many libraries to achieve that. You do not have to make this from scratch.
https://github.com/Cutta/TagView
https://github.com/kaedea/android-tagview
https://github.com/whilu/AndroidTagView
https://github.com/mcharmas/android-tagview
Related
I am using horizontal RecyclerView in Android app.
Showing two items (ImageViews) on the screen at a time.
To do this I am setting the width of each ImageView to half of the screen in ViewHolder class of the adapter:
public static class ViewHolder extends RecyclerView.ViewHolder {
private LinearLayout ll_Img;
private ImageView iv_ad;
private ViewHolder(View v) {
super(v);
ll_Img = (LinearLayout) itemView.findViewById(R.id.ll_Img);
ll_Img.getLayoutParams().width = (Utils.getScreenWidth(itemView.getContext()) / 2);
iv_ad = (ImageView) v.findViewById(R.id.iv_main_ad);
}
}
And getting screen's width:
public static int getScreenWidth(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int screenWidth = size.x;
return screenWidth;
}
It works fine but I want to implement scroll effect like on iOS,
to scroll one item per swipe,
so after each swipe 2 items must fit the screen width.
By the way, two videos worth 1000 words
so here what I am having now:
https://drive.google.com/file/d/0B7j1Rf_oUEbLOWk1OUtpWXFpcEE/view?usp=sharing
And what I want to achieve (as my colleague implemented on iOS):
https://drive.google.com/file/d/0B6B-4-ITg1EQTElNTWsxMWg4aWs/view?usp=sharing
Each piece of advice is appreciated.
This is a viewpager, not a recyclerview. This link might help https://commonsware.com/blog/2012/08/20/multiple-view-viewpager-options.html
Just for anyone else's benefit:
getPageWidth() returns a floating-point number, between 0 and 1,
representing the portion of the width of the ViewPager that a given
page should take up. By default, the page width is 1, but by
overriding this, you can have multiple pages on the screen
simultaneously.
Not entirely sure if this would give the desired effect, but if you are using a linearlayoutmanager, you could add a scrolllistener to your recyclerview, and whenever it gets called, use the linearlayout's method scrollToPosition to force it to scroll all the way to the next item.
Hi I did a research on google, and tried so many solutions on stackoverflow on how to split a large text into multiple TextViews; but none gave me the desired result, not even near to it.
I tried Ellipsis, Measure and so on to calculate the length of the text that fits to a TextView, but they all failed because they were inaccurate, , , and because I use the methods in a BaseAdapter class, I couldn't use them directly, because the view is not rendered on inflation and the sizes are not available before rendering, so I had to use TextView.post(RUNNABLE), to get the width and height of the TextView after the rendering happens.
As I said, the above methods failed, besides of being in accurate, they messed up things a bit and my app became volatile (Exception HELL).
So I thought if there was a way to, render the layout (inflate) in a dummy View/ViewGroup/Activity (I don't know which one), then access the TextView and measure the size of it, this way, I'll make the code more stable, still the methods may be inaccurate, but it worth not doing further changes.
So I make it clear, I need to inflate my XML Layout in a dummy view, to access a child view's width/height.
UPDATE
I can now get the size using following code.
public class MyViewGroup extends LinearLayout {
public MyViewGroup(Context context) {
super(context);
}
}
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
MyViewGroup vg = new MyViewGroup(this);
int width = displayMetrics.widthPixels;
int height = displayMetrics.heightPixels;
vg.setLayoutParams(new LayoutParams(width, height));
View child = (View)ViewGroup.inflate(this, R.layout.content_layout_front_fa, vg);
vg.setVisibility(View.VISIBLE);
int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
vg.measure(measuredWidth, measuredHeight);
vg.layout(0, 0, vg.getMeasuredWidth(), vg.getMeasuredHeight());
vg.requestLayout();
TextView tv = (TextView)child.findViewById(R.id.content);
Log.e("tvW", "" + tv.getWidth());
I m using listfragment in my app. When the data fails to load I call setEmptyText with the failure message. This works fine on 4 inch phones but on 7 and 10 inch phones the size of the empty textview is very small and hard to read.
4 inch empty text view
7 inch empty text view
How can I increase the size of empty text view?
You can provide your own TextView to be used as the "empty text", it just needs to have android:id="#id/android:empty" and the ListFragment will use it instead of the standard one.
You could then customize the style of this TextView however you like (either statically in the xml layout):
<TextView android:id="#id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="... />
or by calling findViewById() in onCreateView():
TextView emptyTextView = (TextView)view.findViewById(android.R.id.empty);
emptyTextView.setTextSize(...);
A (very good) alternative, as #Delblanco commented, is to call getListView().getEmptyView(). It will return either the TextView with id android.R.id.empty (if supplied in the layout), or the standard TextView that is used otherwise.
Here is a drop in extension for ListFragment which changes the size (and color) of the empty view programmatically:
/**
* Abstract list fragment that does customizations of the list style.
*/
public abstract class LoggingListFragment extends ListFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
TextView emptyView = null;
View possibleEmptyView = view.findViewById(0x00ff0001);
if (possibleEmptyView instanceof TextView) {
emptyView = (TextView) possibleEmptyView;
}
if (emptyView == null) {
possibleEmptyView = getListView().getEmptyView();
if (possibleEmptyView instanceof TextView) {
emptyView = (TextView) possibleEmptyView;
}
}
if (emptyView != null) {
emptyView.setTextColor(getActivity().getResources().getColor(R.color.list_subtitle_normal));
emptyView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17);
}
return view;
}
}
Create different folders like res/values-sw720dp,res/values-sw600dp,
res/values-v11.
Create dimen.xml with different font size of different screen size.
Use values/dimen.xml:
<resources>
<dimen name="normal_font">16sp </dimen>
</resources>
4.Use in your widget in your xml.
android:textSize="#dimen/normal_font
I would do it a bit differently.
My idea: find out the dimensions of the screen and use a switch/case statement to adjust your textView text's size.
For example:
switch ( area ) {
case 7inch:
TextView emptyTextView = (TextView)view.findViewById(android.R.id.empty);
emptyTextView.setTextSize(...);
break;
case 4inch:
TextView emptyTextView = (TextView)view.findViewById(android.R.id.empty);
emptyTextView.setTextSize(...);
break;
default:
values_not_caught_above;
}
You can find the dimensions of the screen as follows:
If you want the display dimensions in pixels you can use getSize:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
int area = height*width;
If you're not in an Activity you can get the default Display via WINDOW_SERVICE:
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Before getSize was introduced (in API level 13), you could use the getWidth and getHeight methods that are now deprecated:
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth(); // deprecated
int height = display.getHeight(); // deprecated
I like my way best because it's very easy to just add another case statement for an additional device(may be 10inch screen). Almost nothing in your code will need to change that way.
You may increase the size of the text by calling setEmptyText method with a Spannable, let me show you some code:
String yourEmptyTextMessage = getString(R.string.yourEmptyTextMessage);
Spannable spanText = new SpannableString(yourEmptyTextMessage);
spanText.setSpan(new RelativeSizeSpan(1.5f), 0, yourEmptyTextMessage.length(), 0);
setEmptyText(spanText)
You may want to change 1.5f multiplier value to desired ratio
I'm trying to create Buttons in LinearLayout dynamically, and I want to add those in vertical and horizontal way.
At first, add a button A in the layout, and if there's enough space between button A and screen edge, add button B to the right of button A (horizontally). Otherwise, add button B below button A (vertically).
My current layout :
<LinearLayout
android:id="#+id/btn_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
in class :
LinearLayout btnLayout = (LinearLayout) findViewById(R.id.btn_layout);
btnLayout.removeAllViewsInLayout();
for(Tag tag : tagList.getChildTags()) {
Button button = new Button(this);
button.setId(tag.getId());
button.setText(tag.getName());
btnLayout.addView(button);
}
In this case, if I set orientation as horizontal, then some of buttons are not showing (cut-off by screen), and if I set as vertical, it looks pretty bad.
Is there any way to solve this problem? Thanks everyone in advance!
You can achieve this but not in a trivial way. I'll explain how I do something similar (in my case, I add TextViews) to TableRows, if they fit.
With this approach you'll have to use a TableLayout and add TableRows to it with your Buttons. So you might replace your "#+id/btn_layout" LinearLayout to be a TableLayout instead.
Firstly, to get the screen's width, use something like this:
final Display display = getWindowManager().getDefaultDisplay();
final Point size = new Point();
display.getSize(size);
final WindowManager.LayoutParams params = getWindow().getAttributes();
// Your screen's width will be stored within your params.width value
You'll use this to know if the current Button still fits the screen's width within the current TableRow or it has to be added to a new one. So now, use something like this to create your buttons:
int currentRowsWidth = 0;
TableLayout tl = (TableLayout) findViewById(R.id.my_table_layout);
TableRow currentRow = new TableRow();
for (Tag tag : tagList.getChildTags()) {
Button button = new Button(this);
button.setId(tag.getId());
button.setText(tag.getName());
// There's where you check whether it still fits the current `TableRow` or not
if (currentRowsWidth + button.getWidth() < params.width) {
currentRowsWidth += button.getWidth();
currentRow.addView(button);
}
else {
// It doesn't fit, add the currentRow to the table and start a new one
tl.add(currentRow);
currentRow = new TableRow();
currentRow.addView(button);
currentRowsWidth = button.getWidth();
}
}
It might happen that once you get out of the loop there are still Buttons to add in the currentView, simply test it:
if (currentRow.getChildCound() > 0)
tl.add(currentRow);
I'm writing this from head, so some things might not compile at first time, but I hope you get the idea.
In my app I display several text views containing text of various length that is loaded in at run time. I do not know the dimensions of the text view or the length of the text until run time. Sometimes, when the text is long and the textview small some of the text is partially visible, for example:
I want to remove the partially visible text as it looks a bit naff, but I can't find a way to do this. Any help would be appreciated!
Thanks,
Dave
You can hard code the TextView height in a way that the second row of text will not be visible.
Or use:
android:maxLines , Makes the TextView be at most this many lines tall.
as suggested above.
Put your textviews in a scrollview layout.And specify a specific width to your textview and make the height wrap content.So that your text doesn't get cut.
This is how I did it. I ran this code after the activity had loaded by posting the method CheckTextIsVisible to the parent relativelayout's handler queue, otherwise the height of the textviews will not be known:
m_eventsLayout.Post(new Action(CheckTextIsVisible));
Then the method CheckTextIsVisible finds each textview with text in it, calculates the height of the font, works out how many lines can fit in the textview, and sets the number of maximum lines accordingly:
private void CheckTextIsVisible()
{
View view;
TextView tView;
Android.Text.TextPaint tPaint;
float height;
int heightOfTextView;
int noLinesInTextView;
for (int i = 0; i < m_eventsLayout.ChildCount; i++)
{
view = m_eventsLayout.GetChildAt(i);
if (view is TextView)
{
tView = (TextView)view;
if (tView.Text != "")
{
//calculate font height
tPaint = tView.Paint;
height = CalculateTextHeight(tPaint.GetFontMetrics());
//calculate the no of lines that will fit in the text box based on this height
heightOfTextView = tView.Height;
noLinesInTextView = (int)(heightOfTextView / height);
//set max lines to this
tView.SetMaxLines(noLinesInTextView);
}
}
}
}
private float CalculateTextHeight(Android.Graphics.Paint.FontMetrics fm)
{
return fm.Bottom - fm.Top;
}
This results in no partially visible text!