I have a spinner in a Layout, it is defined as
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/bithYearSpinner"
android:layout_marginTop="15dp" />
Spinner declaration and Adapter:
birthYearSpinner = (Spinner) findViewById(R.id.bithYearSpinner);
String[] years = getResources().getStringArray(R.array.bithYears);
ArrayAdapter<String> adapter = new ArrayAdapter<String(this,android.R.layout.simple_spinner_dropdown_item,years);
birthYearSpinner.setAdapter(adapter);
The problem is, spinner shows up with white text on white background which is impossible to see its items. I have done a research about it, some people have the same problem and there are some solutions but they dont work out for me. How can i fix this ? Any help would be appreciated.
To fix it, you can use custom xml layout for spinner item. By doing this, you can customize your spinner item text color and background.
Create item_spinner.xml and then,
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="19sp"
android:textColor="#111111"
android:padding="8dp"
/>
And set your custom layout to adapter like this :
birthYearSpinner = (Spinner) findViewById(R.id.bithYearSpinner);
String[] years = getResources().getStringArray(R.array.bithYears);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.item_spinner, years);
birthYearSpinner.setAdapter(adapter);
Edit
If it is in fragment, try to replace this with getActivity() . Please look at this answer for reference.
create custom rowlayout for spinner and name it as spinner_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/theme_color"
android:orientation="vertical">
<TextView
android:id="#+id/spinnerText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#ff00ff"
android:gravity="center"
android:paddingBottom="5dip"
android:paddingTop="5dip"
android:text=""
android:textColor="#000000"
android:textSize="18sp" />
</LinearLayout>
now create Adapter and name it as DropDownAdapter.java
package com.ronem.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.ronem.goldsilverpricenepal.R;
public class DropDownAdapter extends ArrayAdapter<String> {
LayoutInflater inflater;
String[] genereValue;
public DropDownAdapter(Context context, int textViewResourceId,
String[] genereValue) {
super(context, textViewResourceId, genereValue);
inflater = LayoutInflater.from(context);
this.genereValue = genereValue;
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(int position, View convertView, ViewGroup parent) {
// LayoutInflater inflater = getLayoutInflater();
convertView = inflater.inflate(R.layout.spinner_item_layou, parent, false);
TextView label = (TextView) convertView.findViewById(R.id.spinnerText);
label.setText(genereValue[position]);
return convertView;
}
}
now initialize and set custom adapter as shown in your activity
DropDownAdapter dAdapter = new DropDownAdapter(this, R.layout.spinner_item_layou, spinnerValues);
itemSpinner.setAdapter(dAdapter);
When i change my resource array <array name=""> to <string-array name="">, spinner items show up properly and no need to use a custom adapter.
Related
I am having an issue with a spinner in my layout.
The issue is that my items have very small width and on a small screen it is pretty hard do click them.
Check the picture for idea.
Is there no easy way of setting the item width to the actual dropdownmenue width?
<android.support.v7.widget.AppCompatSpinner
android:id="#+id/spellSpinner"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:dropDownWidth="match_parent"
android:spinnerMode="dropdown"
android:popupBackground="#fff"
android:background="#8A8A8A"/>
My Java Code:
spinnerSpells = findViewById(R.id.spellSpinner);
ArrayAdapter < CharSequence > adapter = ArrayAdapter.createFromResource(spellActivity.this, R.array.dropdownCategory, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerSpells.setAdapter(adapter);
spinnerSpells.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView << ? > adapterView, View view, int i, long l) {
getSpellList(spinnerSpells.getSelectedItem().toString(), switchSpells.isChecked());
// do some other stuff [...]
}
#Override
public void onNothingSelected(AdapterView << ? > adapterView) {
getSpellList(spinnerSpells.getSelectedItem().toString(), switchSpells.isChecked());
// do some other stuff [...]
}
});
With best regards
CG
P.S. I really did not find any post in the forum about that matter.
To be honest they answer did not really help me, gave me good hint though. I found a way how to solve my problem on my own (also implemented images infront of the labels).
Basically it is the right call to inflate the spinner with a dedicated xml file.
I post my code:
Created a new Class for my adater:
package edmt.dev.androidgridlayout;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class xCustomSpinnerAdapater extends ArrayAdapter<String> {
Context mContext;
String[] spinnerNames;
int[] spinnerImages;
public xCustomSpinnerAdapater( Context mContext, String[] spinnerNames, int[] spinnerImages) {
super(mContext, R.layout.x_custom_spinner, spinnerNames);
this.mContext = mContext;
this.spinnerNames = spinnerNames;
this.spinnerImages = spinnerImages;
}
#Override
public View getDropDownView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.x_custom_spinner,null);
TextView tvSpinnerText = row.findViewById(R.id.tvSpinnerText);
ImageView ivSpinnerImage = row.findViewById(R.id.ivSpinnerImage);
tvSpinnerText.setText(spinnerNames[position]);
ivSpinnerImage.setImageResource(spinnerImages[position]);
return row;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.x_custom_spinner,null);
TextView tvSpinnerText = row.findViewById(R.id.tvSpinnerText);
ImageView ivSpinnerImage = row.findViewById(R.id.ivSpinnerImage);
tvSpinnerText.setText(spinnerNames[position]);
ivSpinnerImage.setImageResource(spinnerImages[position]);
return row;
}
}
Added a xml file accordingly:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal"
>
<ImageView
android:id="#+id/ivSpinnerImage"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:padding="5dp"
android:src="#drawable/artifact"
/>
<TextView
android:id="#+id/tvSpinnerText"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="7"
android:gravity="center"
android:text="Accessory"
android:textSize="18sp"
/>
</LinearLayout>
And after that I edited my mainActivity as follows:
[..]
private xCustomSpinnerAdapater spinnerAdapter;
private String[] spinnerNames = {"All", "Black", "Blue", "Green", "Red"};
private int[] spinnerImages = {R.drawable.artifact, R.drawable.black, R.drawable.blue, R.drawable.green, R.drawable.red};
[..]
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_spell);
spinnerSpells = findViewById(R.id.spellSpinner);
spinnerAdapter = new xCustomSpinnerAdapater(this, spinnerNames,spinnerImages);
spinnerSpells.setAdapter(spinnerAdapter);
spinnerSpells.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(getApplicationContext(),spinnerNames[i],Toast.LENGTH_LONG).show();
[...]
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
[...]
});
The useage of layout_width = "match_parent" in the xml file within in the Linearlayout solved my problem pretty much.
With best regards
CG
use a custom XML file for your spinner item.
say spinner_item.xml and give the customized text size and color if u want
<?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:textSize="20sp"
android:gravity="left"
android:textColor="#FF0000"
android:padding="5dip"
/>
use this file to show your spinner items like:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.spinner_item,list);
Create a separate layout for spinner textview
R.layout.spinner_text
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:maxLines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="your_size_in_dp" />
and set your adapter as follows
ArrayAdapter < CharSequence > adapter = ArrayAdapter.createFromResource(spellActivity.this, R.array.dropdownCategory, R.layout.spinner_text);
Use attribute in xml
android:dropDownWidth="fill_parent| match_parent| wrap_content"
android:spinnerMode="dropdown"
For More Click :
https://developer.android.com/reference/android/widget/Spinner.html#setDropDownWidth(int)
spinner array list Let it be 'dropdownCategory.xml'
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="dropdownCategory">
<item>All</item>
<item>Black</item>
<item>Blue</item>
<item>Green</item>
<item>Red</item>
</string-array>
</resources>
layout having a spinner
<android.support.v7.widget.AppCompatSpinner
android:id="#+id/spellSpinner"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:dropDownWidth="wrap_content"
android:spinnerMode="dropdown"
android:popupBackground="#fff"
android:background="#8A8A8A"/>
In activity.java class within onCreate
Spinner spinnerSpells = findViewById(R.id.spellSpinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(spellActivity.this, R.array.dropdownCategory, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerSpells.setAdapter(adapter);
spinnerSpells.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
// do something [...]
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
// do something [...]
});
I wish this will help you out
Alright, so I'm using a ListView with a custom adapter. Everything works fine and dandy...until the user selects a ListView row and tries to scroll.
When the user selects a row, the background color of that row changes to blue (which is good).
But, problems occur when we begin scrolling: When we scroll past the selected row, the blue fixes itself to either the bottom or the top of the ListView, depending on which way we were scrolling.
Selected row changes color on touch (good)
Part of the background of selected row is fixed to top when scrolling down (not good)
Part of the background of selected row is fixed to bottom when scrolling up (not good)
Here is my source code:
List View that I'm populating dynamically
<ListView
android:id="#+id/tallyDataListView"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:divider="#000000"
android:dividerHeight="1dp"
android:fadeScrollbars="false"
android:listSelector="#0099FF" >
layout_list_view_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<View
android:focusable="false"
android:focusableInTouchMode="false"
style="#style/tableSideBorderLine" />
<TextView
android:id="#+id/COLUMN_PIPE_NUMBER"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
style="#style/tableColumn"
xmlns:android="http://schemas.android.com/apk/res/android" />
<View
android:focusable="false"
android:focusableInTouchMode="false"
style="#style/tableColumnDivider" />
<TextView
android:id="#+id/COLUMN_TOTAL_LENGTH"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
style="#style/tableColumn"
xmlns:android="http://schemas.android.com/apk/res/android" />
<View
android:focusable="false"
android:focusableInTouchMode="false"
style="#style/tableColumnDivider" />
<TextView
android:id="#+id/COLUMN_ADJUSTED"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
style="#style/tableColumn"
xmlns:android="http://schemas.android.com/apk/res/android" />
<View
android:focusable="false"
android:focusableInTouchMode="false"
style="#style/tableSideBorderLine" />
</LinearLayout>
My Custom Adapter
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.ArrayList;
public class ListViewAdapter extends ArrayAdapter<String>{
LayoutInflater inflater;
private final ArrayList<String> adjustedValues;
private final ArrayList<String> pipeNumbers;
private final ArrayList<String> totalLengthValues;
public ListViewAdapter(Activity pContext, ArrayList<String> pPipeNumbers,
ArrayList<String> pTotalLengthValues, ArrayList<String> pAdjustedValues)
{
super(pContext, R.layout.layout_list_view_row, pAdjustedValues);
adjustedValues = pAdjustedValues;
pipeNumbers = pPipeNumbers;
totalLengthValues = pTotalLengthValues;
inflater = pContext.getLayoutInflater();
}
#Override
public View getView(int pPosition, View pView, ViewGroup pParent)
{
View view = inflater.inflate(R.layout.layout_list_view_row, pParent, false);
TextView col1 = (TextView)view.findViewById(R.id.COLUMN_PIPE_NUMBER);
col1.setText(pipeNumbers.get(pPosition));
TextView col2 = (TextView)view.findViewById(R.id.COLUMN_TOTAL_LENGTH);
col2.setText(totalLengthValues.get(pPosition));
TextView col3 = (TextView)view.findViewById(R.id.COLUMN_ADJUSTED);
col3.setText(adjustedValues.get(pPosition));
return view;
}
}
This is the common problem about the listview. When you scroll down it creates the new view every time. That is why the selected element from the top gets out of the focus and another element is selected.
For this problem you have to extend the BaseAdapter class and
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Vehical vehical = vehicals.get(position);
ViewHolder viewHolder = null;
if(convertView==null)
{
viewHolder = new ViewHolder();
convertViewactivity.getLayoutInflater().inflate(R.layout.list_item,null);
convertView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.tvVehicalName = (TextView) convertView.findViewById(R.id.vehicle_name);
viewHolder.tvVehicalName.setText(vehical.getVehicalName());
if(vehical.isSelected()){
viewHolder.tvVehicalName.setTextColor(Color.RED);
}
else
{
viewHolder.tvVehicalName.setTextColor(Color.BLACK);
}
return convertView;
}
//On listener of the listview
searchList.setOnItemClickListener(
new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3) {
if(searchAdapter.isItemSelected(position))
{
searchAdapter.setSelectedItem(position,false);
selectedList.remove(((Vehical)searchAdapter.getItem(position)).getVehicalName());
}
else
{
if(selectedList.size()<new_vehiclelimit){
searchAdapter.setSelectedItem(position,true);
selectedList.add(((Vehical)searchAdapter.getItem(position)).getVehicalName());
}
else
{
Toast.makeText(getApplicationContext(), "Vechicle Limit is Over", Toast.LENGTH_SHORT).show();
}
}
Keep a reference for selected row position in your Adapter, say
int selectedPos = -1;
The value will be -1 when no row is selected. And in the OnItemClickListener of the listview,update selectedPos with the clicked position and call notifyDatasetChanged() on the adapter. In the getView method of the adapter, check for the selectedPos value and highlight the row accordingly.
I'm trying to build a ListView with a custom layout but so far have not been able to successfully do it. I'm a beginner and have been following tutorials to get it done.
This is what I'm doing:
//this is where I want the custom list items to be displayed.
//GroupAdapter is the constructor of the class in which I'm trying to make a custom adapter
stringArray = new String[10];
groupItemArrayAdapter = new GroupAdapter(this,stringArray);
groupListView = (ListView) findViewById(R.id.mainList);
groupListView.setAdapter(groupItemArrayAdapter);
//this is the code in GroupAdapter.java class
public class GroupAdapter extends ArrayAdapter{
private LayoutInflater inflater;
public GroupAdapter(Activity activity, String[] items){
super(activity,R.layout.group_view);
inflater=activity.getWindow().getLayoutInflater();
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
return inflater.inflate(R.layout.group_view,parent,false);
}
}
When i start the app, a blank screen appears. Initially when i used Android default layout for the list, list items were displayed but not anymore... I don't understand what I'm doing wrong. Can anyone help?
Here is the group_view.xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="30dp" >
<TextView
android:id="#+id/gName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Group Name"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_marginRight="100dp"
android:textStyle="bold" />
<TextView
android:id="#+id/activity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/signIn"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="5"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textStyle="bold" />
</LinearLayout>
You can replace all your code by next
stringArray = new String[10];
groupItemArrayAdapter = new GroupAdapter(this,stringArray);
groupListView = (ListView) findViewById(R.id.mainList);
groupListView.setAdapter(new ArrayAdapter<String>(this, R.layout.group_view, R.id.gName, stringArray));
it's for case when you want to show strings at gName field, if you want to shot them at activity, then you need to use
groupListView.setAdapter(new ArrayAdapter<String>(this, R.layout.group_view, R.id.activity, stringArray));
Answer for "Why it's blank?"
#Override
public View getView(int position, View convertView, ViewGroup parent){
return inflater.inflate(R.layout.group_view,parent,false);
}
You only inflate empty view and does not assign strings to fields. It would be (simplest version)
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = inflater.inflate(R.layout.group_view, parent, false);
TextView textView = (TextView)convertView.findViewById(R.id.gName);
String item = getItem(position)
textView.setText(item);
return convertView;
}
You'll be able to implement better version after read article Making ListView Scrolling Smooth
EDIT: This problem has been resolved, so the code in my original post does not apply anymore. Thanks to everyone who contributed.
First off, I have checked other similar questions but they either don't match mine or use the BaseAdapter. What I'm trying to do is display a text-image combination as part of a GridView. The actual app is larger, but my problem is that the GridView is blank in the very first activity!
I'd appreciate if someone can take a quick look at it and tell me what's wrong.
Code for layout file used for GridView elements:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical" >
<ImageView
android:id="#+id/iv_grid"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/ic_launcher" />
<TextView
android:id="#+id/tv_grid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
Layout file of first Activity:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".CategoriesActivity" >
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="54dp"
android:text="Select a category to learn more" />
<TextView
android:id="#+id/tv_grid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="26dp"
android:text="Lessons from History"
android:textSize="18sp" />
<GridView
android:id="#+id/gridView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/textView2"
android:layout_marginTop="25dp"
android:numColumns="3" >
</GridView>
</RelativeLayout>
And finally, the Java file:
package com.example.historicpersonalities;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
public class CategoriesActivity extends Activity {
GridView gv_categories;
public int selected; //which category is selected [0-4]?
String[] data; //holds the data for GridView
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_categories);
populate();
selected = -1;
gv_categories = (GridView) findViewById(R.id.gridView1);
gv_categories.setAdapter(new MyAdapter(this,
android.R.layout.simple_expandable_list_item_1));
gv_categories.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int index,
long arg3) {
}
});
}
class MyAdapter extends ArrayAdapter<String> {
public MyAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.layout_grid_scheme, null);
TextView item = (TextView) findViewById(R.id.tv_grid);
item.setText(data[position]);
ImageView img = (ImageView) findViewById(R.id.iv_grid);
img.setImageResource(R.drawable.dummy);
Log.d("ankush", ""+position);
return v;
}
}
private void populate() {
data = new String[5];
data[0] = "Writers";
data[1] = "Painters";
data[2] = "Conquerors";
data[3] = "Chemists";
data[4] = "Actors";
}
}
I think the problem is the height of your gridView. GridView is a scrollable container and can contain any amount of content in any height. Try to set background color to your gridView and you will see, that there is no gridview on the screnn.
It's because you use wrap_content for gridview, but it's incorrect.
If I'm not wrong, it seems that in your constructor you don't pass any data to the adapter.
public MyAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
}
In this code snippet, your are using ArrayAdapter (Context context, int textViewResourceId) which initialize an empty arraylist as the objects to represent in the GridView.
public ArrayAdapter(Context context, int textViewResourceId) {
init(context, textViewResourceId, 0, new ArrayList<T>());
}
Therefore your GridView should be empty. In addition to that, it seem you didn't properly implement the getView.(findViewById() parts should be handled as shown in the Opiatefuchs's answer)
If you want to extend ArrayAdapter, you should be calling a constructor which takes an array of objects as a parameter. (Of course there are many ways to make a custom adapter you can extend BaseAdapter or while extending ArrayAdapter you can override some other methods)
This way it should work:
class MyAdapter extends ArrayAdapter<String> {
public MyAdapter(Context context, int textViewResourceId, String[] objects) {
super(context, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.layout_grid_scheme, null);
} else {
view = convertView;
}
TextView item = (TextView) view.findViewById(R.id.tv_grid);
item.setText(getItem(position));
ImageView img = (ImageView) view.findViewById(R.id.iv_grid);
img.setImageResource(R.drawable.dummy);
}
}
Don´t know if this causes the problem, but You have to set Your TextView and ImageView in Your adapter like this:
TextView item = (TextView) v.findViewById(R.id.tv_grid);
item.setText(data[position]);
ImageView img = (ImageView) v.findViewById(R.id.iv_grid);
img.setImageResource(R.drawable.dummy);
EDIT
First of all, the best way is to combine all three solutions. BUT, I have seen another issue in Your xml layout: You put the same id to the TextView inside Your GridView Element xml and Your Activity layout xml. Both TextViews got id="#+id/tv_grid" . This could never work, change the id´s to different ones
I'm having an issue getting my list populated correctly by my custom ArrayAdapter (code below). As I understand it, my adapter is only populating the textviewResourceId when it is instanciated since I'm using constructor Adapter(context, rowLayout, textViewResourceId, ArrayList<Items>), but the getView method is only called when rows that were not visible become visible.
This is causing an issue as, when my list is first showing, only the title of my article is showing, and I have to scroll all the way down the list and up for all the views in each row to be populated correctly (since that task is done in getView).
Can anyone point me in the right direction? How could I refactor this so all views in each visible row gets populated right away?
Code to my custom adapter:
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class ArticleArrayAdapter extends ArrayAdapter<Article> {
private final Context context;
private final ArrayList<Article> articles;
#SuppressWarnings("unused")
private final int rowLayout;
public ArticleArrayAdapter(Context context, int rowLayout, int textViewResourceId, ArrayList<Article> articles) {
super(context, rowLayout, textViewResourceId, articles);
this.rowLayout=rowLayout;
this.context = context;
this.articles = articles;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null) {
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(R.layout.affichageitem, null);
}
else {
TextView viewTitre = (TextView)row.findViewById(R.id.titre);
TextView viewAuteur = (TextView)row.findViewById(R.id.auteur);
TextView viewDate = (TextView)row.findViewById(R.id.date);
ImageView viewLogo = (ImageView)row.findViewById(R.id.category_logo);
viewTitre.setText(articles.get(position).getTitle());
viewAuteur.setText(articles.get(position).getCreator());
viewDate.setText(articles.get(position).getDate());
Drawable drawLogo = context.getResources().getDrawable(R.drawable.logocat);
viewLogo.setImageDrawable(drawLogo);
}
return super.getView(position, convertView, parent);
}
}
Edited version:
public class ArticleArrayAdapter extends ArrayAdapter<Article> {
private final Context context;
#SuppressWarnings("unused")
private final int rowLayout;
public ArticleArrayAdapter(Context context, int rowLayout,int textViewResourceId) {
super(context, rowLayout, textViewResourceId);
this.rowLayout=rowLayout;
this.context = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null) {
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(R.layout.affichageitem, null);
}
else {
TextView viewTitre = (TextView)row.findViewById(R.id.titre);
TextView viewAuteur = (TextView)row.findViewById(R.id.auteur);
TextView viewDate = (TextView)row.findViewById(R.id.date);
ImageView viewLogo = (ImageView)row.findViewById(R.id.category_logo);
viewTitre.setText(getItem(position).getTitle());
viewAuteur.setText(getItem(position).getCreator());
viewDate.setText(getItem(position).getDate());
Drawable drawLogo = context.getResources().getDrawable(R.drawable.logocat);
viewLogo.setImageDrawable(drawLogo);
}
return super.getView(position, convertView, parent); // <<- ONLY TITLES
//return row; <<- EMPTY
}
}
rowLayout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<ImageView
android:id="#+id/category_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:contentDescription="#string/logo_desc"
android:padding="20dp" />
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingLeft="5dp" >
<TextView
android:id="#+id/titre"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="18dp"
android:textStyle="bold" />
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity=""
android:orientation="horizontal" >
<TextView
android:id="#+id/auteur"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:textSize="12dp" />
<TextView
android:id="#+id/espace"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/espace"
android:adjustViewBounds="true"
android:textSize="12dp" />
<TextView
android:id="#+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:textSize="12dp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
The problem is that you are not populating new views. What happens is that Android may keep a fixed number of views which will be used for your list view. The views are recycled which is why it's impossible to "populate" all your views before they become visible. This line
if (view == null) {
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(R.layout.affichageitem, null);
}
checks whether a view is being recycled or not. null means it's not, so if you get null you need to inflate a new view. Upto there your code's fine. However, you need to populate the view whether it's a newly inflated view or not. So you shouldn't have the else statement, just have
View row = convertView;
if (row == null) {
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(R.layout.affichageitem, null);
}
TextView viewTitre = (TextView)row.findViewById(R.id.titre);
TextView viewAuteur = (TextView)row.findViewById(R.id.auteur);
TextView viewDate = (TextView)row.findViewById(R.id.date);
ImageView viewLogo = (ImageView)row.findViewById(R.id.category_logo);
viewTitre.setText(getItem(position).getTitle());
viewAuteur.setText(getItem(position).getCreator());
viewDate.setText(getItem(position).getDate());
Drawable drawLogo = context.getResources().getDrawable(R.drawable.logocat);
viewLogo.setImageDrawable(drawLogo);
return row;
The reason why it worked when you scrolled all the way down is that on your way back up getView was receiving recycled views and it jumped right into the else clause you had.
You are using your own collection ArrayList<Article>.
Note that every ArrayAdaper<foo> already has data collection built in, where you can add by add(foo) or addAll(List<foo>) and clear it by clear() method.
Also, ListView can observe this data and refresh when changes happen to this data. Or explicitly when notifyDataSetChanged() is called on adapter.
Problem here is that you are accepting data in constructor, storing in yet another local variable, and notifyDataSetChanged() is not being called. You cannot call it from constructor as Object is still under construction.
So, Don't accept data in constructor. Inside getView() use getItem(position) to get Article item.
Add data externally like:
ArticleArrayAdapter adapter = new ArticleArrayAdapter(context,rowLayout,android.R.layout.simple_list_item_1);
adapter.addAll(articles);
myListView.setAdapter(adapter);
Looks correct to me - only thing: there is no need to call the superclass. Try to return your assembled view like that:
return row;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row==null){
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(R.layout.affichageitem, null);
convertView.setTag(row);
}else{
TextView viewTitre = (TextView)row.findViewById(R.id.titre);
TextView viewAuteur = (TextView)row.findViewById(R.id.auteur);
TextView viewDate = (TextView)row.findViewById(R.id.date);
ImageView viewLogo = (ImageView)row.findViewById(R.id.category_logo);
viewTitre.setText(getItem(position).getTitle());
viewAuteur.setText(getItem(position).getCreator());
viewDate.setText(getItem(position).getDate());
Drawable drawLogo = context.getResources().getDrawable(R.drawable.logocat);
viewLogo.setImageDrawable(drawLogo);
}
}
I had this similar kind of issue. I also found that without scrolling manually to the last of the list all views were not created. All items were null except visible items.So, I had to scroll down to the last of the list programmatically.
I have extended MyAdapter from BaseAdapter class.
mAdapter = new MyAdapter(this, mFinalContactList);
mListView.setAdapter(mAdapter);
To auto scrolling to last with all listview created I have used following lines of code.
mAdapter.notifyDataSetChanged();
mListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
mListView.smoothScrollToPosition(mFinalContactList.size()-1);
This might help some one who are trying auto scroll to the last.
N.B. mListView.setSelection(position); method only can point the last list item if we set the position to last. But can not populate the list item from forst to last.
Thank you