I have a spinner that allows me to not show the first item in the list, but i can set my custom prompt. However whenever the prompt text spans more than one line it is cut off at the view bounds. How can i make the spinner prompt expand to accommodate more text?
I have tried modifying the view passed into the adapter to have multiple lines and also to ellipsize at the end, but nothing works.
Images for clarity:
With one line of text,
With several lines,
This is my code:
languagesSpinner.setAdapter(new ArrayAdapter<>(EditProfileNationalityActivity.this, R.layout.no_default_spinner_item, new String[] {""}));
if(data.length>0) {
String countries = spokenLanguages.toString().substring(0, spokenLanguages.toString().length() - 2);
languagesSpinner.setPrompt(countries);
} else {
Log.e("setting prompt to default");
languagesSpinner.setPrompt("Please select languages");
}
and this is the xml file:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_gravity="center_vertical"
android:textColor="#android:color/black"
android:textSize="18sp"
android:ellipsize="end"
android:lines="2"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:background="?android:attr/activatedBackgroundIndicator" />
Per request, xml definition of spinner is as follows:
<com.package.views.NoDefaultSpinner
android:id="#+id/registration_stage_4_country_languages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:clickable="false" />
NoDefaultSpinner.java can be found here: https://github.com/geftimov/android-components/blob/master/components/src/main/java/com/eftimoff/components/views/spinners/nodefault/NoDefaultSpinner.java
I have modified it to have a custom getView() method in the SpinnerProxy like this:
if (position < 0) {
if (layoutResource == -1) {
layoutResource = R.layout.no_default_spinner_item;
}
final TextView v =
(TextView) ((LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE)).inflate(
layoutResource, parent, false);
v.setText(getPrompt());
v.setPadding(0, 5, 0, 5);
return v;
}
return obj.getView(position, convertView, parent);
}
I edited your source code:
adapter = new ArrayAdapter<>(EditProfileNationalityActivity.this, R.layout.no_default_spinner_item, new String[] {""});
adapter.setDropDownViewResource(R.layout.no_default_spinner_item);
languagesSpinner.setAdapter(adapter);
Related
I have a ListView and a custom adapter. Now i have red posts about getView() method being called multiple times, and most of them have to do with the wrap_content feature of the ListView.
I have changed my height, so that it can be match_parent but still, the method is being called.
I think it has something to do with adding TextViews dynamically in the adapter, and i don't know how to do it, so it works properly.
If there is an alternative, i am opened to it, the only reason why i put TextViews is so that i can have letters written in different colors.
Here is my code:
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
Row current = mList.get(position);
/* if the given channel row view is not being updated*/
if (v == null)
{
/* inflate layout */
LayoutInflater vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.list_item2, null,false);
}
v = setLinearLayout(v,current);
return v;
}
Here is the setLinearLayout() method:
private View setLinearLayout(View v,Row current) {
ArrayList<Integer> winResults = current.checkNumbers(mResult,mType);
int numbers[] = current.getNumbers();
int N = Global.getNumberOfNumbers(mType);
boolean FLAG_SET = false;
final TextView[] myTextViews = new TextView[N]; // create an empty array;
for (int i = 0; i < N; i++) {
Log.d("PAVLE",""+i+" row is: "+current.getStringNumbers());
// create a new textview
final TextView rowTextView = new TextView(v.getContext());
LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,75);
rowTextView.setTextSize(24.0f);
rowTextView.setPadding(8, 8, 8, 8);
rowTextView.setGravity(Gravity.CENTER);
rowTextView.setBackgroundColor(Color.BLACK);
rowTextView.setTypeface(null, Typeface.BOLD);
rowTextView.setLayoutParams(lp);
if(mType == R.string.sans_topu && i == 5 && !FLAG_SET){
i--;
rowTextView.setTextColor(Color.WHITE);
rowTextView.setText("+");
FLAG_SET = true;
}
else {
// set some properties of rowTextView or something
if (mWin == Global.WIN || mWin == Global.LOSE) {
if (winResults.contains(numbers[i]))
rowTextView.setTextColor(Color.GREEN);
else rowTextView.setTextColor(Color.RED);
} else {
rowTextView.setTextColor(Color.WHITE);
}
if (numbers[i] < 10) {
rowTextView.setText("0" + numbers[i]);
} else rowTextView.setText("" + numbers[i]);
}
// add the textview to the linearlayout
LinearLayout ll = (LinearLayout) v.findViewById(R.id.ll_item);
ll.addView(rowTextView);
// save a reference to the textview for later
myTextViews[i] = rowTextView;
}
final TextView prize = new TextView(v.getContext());
LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,75);
prize.setTextSize(24.0f);
prize.setPadding(8, 8, 8, 8);
prize.setGravity(Gravity.CENTER);
prize.setBackgroundColor(Color.BLACK);
prize.setTypeface(null, Typeface.BOLD);
prize.setTextColor(Color.WHITE);
prize.setLayoutParams(lp);
try {
String cash = findCorretAmmount(winResults, numbers);
prize.setText(cash);
mTotal.append(" "+cash);
}
catch (Exception e){
e.printStackTrace();
}
LinearLayout ll = (LinearLayout) v.findViewById(R.id.ll_item);
ll.addView(prize);
return v;
}
And a little bit of XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tvRandomTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="16dp"
android:paddingRight="8dp"
android:text="#string/your_ticket_numbers_"
android:textColor="#android:color/black"
android:textSize="28sp"
android:textStyle="bold"
/>
<View
android:id="#+id/divider4"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="#id/tvRandomTextView"
android:layout_marginBottom="4dp"
android:layout_marginTop="4dp"
android:background="#android:color/darker_gray"/>
<ListView
android:id="#+id/lvRowList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/divider4"
/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
>
<Button
android:id="#+id/btnDelete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="#string/delete"/>
<Button
android:id="#+id/btnShare"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="#string/btn_share"/>
<Button
android:id="#+id/btnDone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="#string/done"/>
</RelativeLayout>
<TextView
android:id="#+id/tvResultLink"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="4dp"
android:layout_marginTop="4dp"
android:autoLink="web"
android:gravity="center"
android:linksClickable="true"
/>
Also worth mentioning is that list_item2(LinearLayout) has height of 100dp, it's fixed size.
I think its not about textview.
The getView is always called multiple times. If you have 10 items on the screen to be shown, the getView going to be called 15 times, because the android creating views that are not on the screen. It`s good, because when the user start scrolling, it is not going to lagging.
After the user left the item, the view get`s recycle and reused by the adapter. Lets say, you have a list with 10000000 item, but you have 5 item on the screen at all time. In this case - to save power, and improve performance - the android going to create 10 list item, and this 10 item is going to recylce and refresh by content.
ViewHolder pattern
Please read this and use this patter to improve your code performance:
http://developer.android.com/training/improving-layouts/smooth-scrolling.html
Google about ListView:
http://developer.android.com/guide/topics/ui/layout/listview.html
Tutorials:
http://developer.xamarin.com/guides/android/user_interface/working_with_listviews_and_adapters/
I'm trying to change background color on a view component, but not success
public View getView(int position, final View convertView, ViewGroup parent) {
View view = convertView;
try {
if (view == null) {
LayoutInflater vi = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.listview_accounts, null); // --CloneChangeRequired(list_item)
}
final Account listItem = (Account) mList.get(position); // --CloneChangeRequired
if (listItem != null) {
int color = listItem.getColor();
View vColor = (View) view
.findViewById(R.id.lv_account_view_color);
vColor.setBackgroundColor(color);
}
}
} catch (Exception e) {
}
return view;
}
I can set some text in textview, but set color not working.
Can anybody helps me how to set the color? Thanks
The example color used is: -16711717
edit
Listview Item layout:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<View
android:id="#+id/lv_account_view_color"
android:layout_width="#dimen/activity_horizontal_margin"
android:layout_height="wrap_content"
android:background="#167117" />
<TextView
android:id="#+id/lv_account_tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/activity_horizontal_margin"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:layout_marginTop="#dimen/activity_horizontal_margin"
android:textColor="#color/black" />
</LinearLayout>
background cannot be setted in xml, it's a dynamic color
Try this: vColor.setBackgroundColor(Color.parse("#yourcolorcode"));
You can directly set the background color of the component in the listview_accounts.xml file of your project. For example
<component>
android:background="#color/color_name"
</component>
You have to make a color.xml file in your values folder(maybe already present) and add the color value ex:-16711717.
try this and let me know
<View
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#167117" />
you can find solution on This link
Just you have to change one thing. In delete.onclick method replace list.removeView(customView); with Customview.setbackground(Color.red); etc. This may help you. Best of luck.
I am facing EXTREMELY PECULIAR problem with my android application. I see not a single similar solution anywhere, either on google or on SO.
Here is my screenshot of the app:
This is normal expected output. But when I exit the app and resume again from launcher, often(say 2 out of 5 times) I happen to get the white components(list view and EditText) like this:
In this image, I have touched the first element of listview while taking screenshot so that its shown that the listview items are having actual content and not empty.
Here is my layout resource file main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ll"
android:cacheColorHint="#00000000"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" android:weightSum="15" android:background="#android:color/white">
<EditText
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="#+id/edittext" android:layout_weight="2" android:background="#ffffff"
android:textColor="#android:color/black" android:gravity="center" android:hint="Enter Your Text Here"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp" android:layout_weight="2"
android:weightSum="12" android:gravity="center">
<Button android:layout_width="0dp"
android:layout_height="match_parent"
android:text="Tweet"
android:id="#+id/tweetbtn"
android:background="#drawable/mybutton"
android:layout_weight="6"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:text="Search"
android:background="#drawable/mybutton"
android:id="#+id/searchbtn"
android:layout_weight="6"/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:text="Most Frequently Tweeted"
android:id="#+id/listviewlabel" android:layout_weight="1" android:gravity="center" android:background="#adadad"
android:textColor="#android:color/black"/>
<ListView
android:cacheColorHint="#00000000"
android:background="#ffffff"
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="#+id/listView" android:layout_gravity="center_horizontal" android:layout_weight="10"
android:choiceMode="singleChoice"/>
</LinearLayout>
Please someone help me out with this. Atleast help me resolve the white EditText issue first. That will give me alteast a clue to solve the listview issue.
EDIT:
The listview is dynamically populated by elements. Here is my onStart() method:
#Override
public void onStart(){
super.onStart();
handleFrequentMenuSelected();
}
Here is the handleFrequentMenuSelected():
private void handleFrequentMenuSelected() {
if(!isAccountAdded()){
showToast("Add an account first to get started! Goto Menu and select account.");
}else{
List<StatusElement>aList=getStatusElementsFromSQLiteDatabase();
HashMap<String,Integer> hMap=new HashMap<String, Integer>();
for(StatusElement s:aList){
String tokens[]=s.toString().split(" ");
String outText="";
if(tokens.length>1){
if(tokens[0].contains("/")){
String tokens2[]=tokens[0].split("/");
try{
long l=Long.parseLong(tokens2[0]);
for(int i=1;i<tokens.length;i++){
outText=outText+tokens[i]+" ";
}
}catch(Exception e){
outText=s.toString();
}
}else{
try{
long l=Long.parseLong(tokens[0]);
for(int i=1;i<tokens.length;i++){
outText=outText+tokens[i]+" ";
}
}catch(Exception e){
outText=s.toString();
}
}
}else{
outText=s.toString();
}
outText=outText.trim();
if(hMap.containsKey(outText)){
int cnt=hMap.get(outText);
cnt++;
hMap.put(outText,cnt);
}else{
hMap.put(outText,1);
}
}
hMap= (HashMap<String, Integer>) StaticConstants.sortByValue(hMap);
ArrayList<String>tweets=new ArrayList<String>();
ArrayList<Integer>frequencies=new ArrayList<Integer>();
ArrayAdapter<String>adapter;
int count=0;
for(String s:hMap.keySet()){
tweets.add(s);
frequencies.add(hMap.get(s));
count++;
if(count==50)
break;
}
adapter=new MyCustomFrequentArrayAdapter(this,tweets,frequencies);
listView.setAdapter(adapter);
listViewLabel.setText("Most Frequent Tweets");
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, final View view,
int position, long id) {
final String item = (String) parent.getItemAtPosition(position);
editText.setText(System.currentTimeMillis()+" "+item);
}
});
}
}
Here is my MyCustomFrequentArrayAdapter:
class MyCustomFrequentArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private final ArrayList<String> values;
private final ArrayList<Integer>frequencies;
public MyCustomFrequentArrayAdapter(Context context, ArrayList<String> values,ArrayList<Integer>frequencies) {
super(context, R.layout.customlistview, values);
this.context = context;
this.values = values;
this.frequencies=frequencies;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.customlistview, parent, false);
TextView textView1 = (TextView) rowView.findViewById(R.id.firstLine);
TextView textView2 = (TextView) rowView.findViewById(R.id.secondLine);
Log.d("Position",""+position);
//Extracting first six words
String s=values.get(position);
String tokens[]=s.split(" ");
String dispText="";
if(tokens.length>6){
for(int i=0;i<6;i++){
dispText=dispText+tokens[i]+" ";
}
}else{
dispText=s;
}
textView2.setText(dispText);
textView1.setText("Frequency:"+frequencies.get(position));
return rowView;
}
}
Referencing a blog post by Romain Guy - Why Is My List Black
ListView has top and bottom fading edges to indicate it is scrollable.
Creating the fading edge has performance issues so ListView has an optimization to improve performance. Unfortunately the optimization causes problems if the background of the ListView is set to something other than the default.
The optimization can be disabled by setting android:cacheColorHint="#00000000" as you are doing BUT quoting from the blog post...
To fix this issue, all you have to do is either disable the cache color hint optimization, if you use a non-solid color background, or set the hint to the appropriate solid color value.
In other words using android:cacheColorHint="#00000000" should only be used for a "non-solid color" (one which is transparent / translucent).
In your case you are using #ffffff which is an RGB value and by default that means its 'A' component (the alpha) will be ff making it fully opaque, i.e., "solid".
So referring to the last part of the above quote...
...set the hint to the appropriate solid color value.
This suggests you should use android:cacheColorHint="#ffffff" to fix the ListView problem.
I want to accomplish the below :
I want to categorize the items inside the listview, however, my listviews tend to appear only one rowed because I am only giving it one one (custom xml, extended custom baseadapter)
I checked this link , however it does not seem to do what I want to accomplish, any hints ?
You could add an initially hidden (View.GONE) header to your row's XML and fill it and show it when a category change is detected.
Another more efficient option would be inflating / creating and adding this header (which could be any kind of View or ViewGroup) programmatically when the category change is detected.
For example (first option):
row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rowContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/txtGroupHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:padding="4dp"
android:background="#drawable/group_header_gradient"
android:gravity="center"
android:textColor="#android:color/white" />
<ImageView
android:id="#+id/imgLogo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:layout_marginLeft="3dp"
android:layout_marginRight="5dp"
android:layout_alignParentLeft="true"
android:layout_below="#id/txtGroupHeader" />
</RelativeLayout>
Adapter code
#Override
public View getView(int position, View convertView, ViewGroup parent){
View res = null;
Pojo ev = (Pojo)this.getItem(position);
Integer prevItemType = null;
//Get the type of the previous pojo in the list
if(position > 0){
Pojo prevEv = (Pojo)this.getItem(position - 1);
if(prevEv != null){
prevItemType = prevEv.getType();
}
}
//Determine if this view should have a header
boolean addHeaderView = !(prevItemType != null && prevItemType.equals(ev.getType()));
if(convertView != null){
res = convertView;
}else{
res = mInflater.inflate(R.layout.row, null);
}
TextView txtHeader = (TextView)res.findViewById(R.id.txtGroupHeader);
if(addHeaderView){
String typeName = Database.getTypeDescription(ev.getType());
if(typeName != null){
txtHeader.setText(typeName.toUpperCase(Locale.US));
}
txtHeader.setVisibility(View.VISIBLE);
}else{
txtHeader.setVisibility(View.GONE);
}
//Regular row
ImageView imgLogo = (ImageView)res.findViewById(R.id.imgLogo);
// ... imgLogo.setImageBitmap ...
// ... etc ...
return res;
}
Hope it helps.
I'm having a weird problem, in my rather complex view layout. (I will try to simplify it a bit in my explanation)
Basically I have a ListView, where each item consists of a TextView and an ImageButton. I am able to either click the list item (on the textview), or the button (I set the ImageButton to non-focusable, otherwise it wouldn't work)
Now it seems to work fine, until I open another window and return to the listview.
From that point on, I can click the ImageButton without anything happening (not even the background changes during the click). But when I click on the TextView again, all the click events from the ImageButton are dispatched at once.
Why is that?
EDIT:
The List Item:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="0px"
android:minHeight="40dp"
android:orientation="horizontal"
android:paddingLeft="2px"
android:paddingRight="2px"
>
<TextView
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Text"
android:textSize="19dp"
android:paddingTop="4px"
android:paddingBottom="4px"
android:layout_gravity="center_vertical"/>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/open_subtree_layout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="0px"
android:orientation="horizontal"
android:padding="0px">
<View
android:layout_width="1px"
android:layout_height="match_parent"
android:background="#drawable/separator_line" />
<com.treeviewer.leveldisplay.DontPressWithParentImageButton
android:id="#+id/btn_right"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:background="#drawable/list_selector_background"
android:focusable="false"
android:focusableInTouchMode="false"
android:padding="10dp"
android:src="#drawable/arrow_right" />
</LinearLayout>
</LinearLayout>
That's how it is inflated:
[...]
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mView = inflater.inflate(R.layout.tree_row, null, false);
TextView textView = (TextView)mView.findViewById(R.id.text1);
LinearLayout nextNodeButtonContainer = (LinearLayout)mView.findViewById(R.id.open_subtree_layout);
if(childCount >= 0) {
titleBuilder.append(" (" + childCount + ")");
nextNodeButtonContainer.setVisibility(View.VISIBLE);
View button = nextNodeButtonContainer.findViewById(R.id.btn_right);
button.setFocusable(false);
button.setFocusableInTouchMode(false);
//button.setClickable(true);
button.setOnClickListener(clickListener);
button.setTag(tagValue);
} else {
nextNodeButtonContainer.setVisibility(View.GONE);
}
textView.setText(titleBuilder);
Let me know, if you need more code.
Ok, I finally solved this problem.
Unfortunately, in my question I didn't provide the necessary information to solve it, as the problem was somewhere I didn't expect it:
I have a ListAdapter where the getView method looks like this:
public View getView(int position, View convertView, ViewGroup parent) {
return mNodes.get(position).getView(mNodeArrowClickListener, position);
}
And the getView method of the nodes (TreeLevelElements) looked like:
public class TreeLevelElement {
private final Context mContext;
private View mView = null;
//[...] other methods
View getView(OnClickListener clickListener, final int tagValue) {
if(mView == null) {
//[...] produce a new View from XML
}
return mView;
}
}
The problem was, that I stored the Views in my elements, so I guess that conflicted somehow with android strategy to reuse old views for new items.
I don't know what exactly happened, but now that I removed mView and create a new one every time, it works.
I will also change it to reuse the convertView instead.