Drawing rectangle in Custom ListView in android - android

I have to draw a custom shapes inside the ListView rows in android. I found this on web but couldn't succeed. I have a class DrawView.java which makes a rectangle on Canvas and I want the object of this class to be included in my custom ListView rows.
DrawView.java
package com.example.horizontalscrollview;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class DrawView extends View {
Paint paint = new Paint();
public DrawView(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
paint.setColor(Color.BLACK);
paint.setStrokeWidth(3);
canvas.drawRect(30, 30, 180, 180, paint);
}
}
and my xml file for a row of Custom ListView is
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="60dp"
android:id="#+id/mainLayout"
>
<com.example.horizontalscrollview.DrawView
android:id="#+id/drawview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
</com.example.horizontalscrollview.DrawView>
</LinearLayout>
and getView() function of custom Adapter of ListView is:
public View getView(final int position, View convertView, final ViewGroup parent) {
Toast.makeText(c, "Clicked on="+position, 1).show();
convertView = mInflater.inflate(R.layout.news_list_item,null);
DrawView rl = (DrawView)convertView.findViewById(R.id.drawview);
DrawView draw = new DrawView(c);
rl=draw;
return convertView;
}

inflate this xml in your get view method
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="60dp"
android:id="#+id/mainLayout"
>
<com.example.horizontalscrollview.DrawView
android:id="#+id/drawview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
</com.example.horizontalscrollview.DrawView>
</LinearLayout>
here is get view method
public View getView(final int position, View convertView, final ViewGroup parent) {
Toast.makeText(c, "Clicked on="+position, 1).show();
convertView = mInflater.inflate(R.layout.news_list_item,null);
return convertView;
}
it should work fine, if this isn't working please let known the issue :)
happy coding

Related

Give spinner items the width of its dropdown

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

ListView rows with rounded corners

I am currently working on rewriting one of my iOS apps to release on Android. I'm making good progress but I am looking for some guidance regarding the best way to approach the list rows.
These are the cells/rows I am trying to recreate:
As you can see, I have a white background view with padding around each edge and rounded corners, so I guess for this I would need to embed everything within a view of some sort? The other part I am unsure about is how to create the coloured circle on the right. Would this be another view with rounded corners and a coloured background? I haven't managed to figure out how to get this to the right of the two textViews that I currently have. So if anyone could give a code example then that would be great.
This is my current XML:
<ImageView
android:layout_width="78dp"
android:layout_height="78dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:scaleType="centerCrop"
android:adjustViewBounds="false"
android:id="#+id/attractionImageView"
android:contentDescription="Attraction Image"
android:background="#color/colorPrimary" />
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:background="#drawable/fast_pass"
android:id="#+id/fastPassImageView" />
<LinearLayout android:orientation="vertical" android:layout_height="match_parent" android:layout_width="fill_parent" android:layout_toEndOf="#+id/attractionImageView" android:layout_toRightOf="#+id/attractionImageView">
<TextView
android:layout_width="match_parent"
android:layout_height="49dp"
android:id="#+id/attractionNameTextView"
android:text="Attraction Name"
android:layout_marginLeft="5dp"/>
<LinearLayout android:orientation="horizontal" android:layout_height="match_parent" android:layout_width="fill_parent" android:layout_toEndOf="#+id/attractionImageView" android:layout_toRightOf="#+id/attractionImageView">
<ImageView
android:layout_width="13dp"
android:layout_height="13dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:id="#+id/updatedImageView"
android:background="#drawable/updated"
android:layout_gravity="center_vertical"/>
<TextView
android:layout_width="match_parent"
android:layout_height="29dp"
android:id="#+id/updatedTextView"
android:text="Updated"
android:gravity="center_vertical"/>
</LinearLayout>
</LinearLayout>
This seems to work well for everything I've got so far, but I'm not sure where to go from here. This is how it looks:
Any suggestions?
For the colored circle- I'd suggest just a text view set to the proper size with a circle drawable set as the background of the view. Should get what you want.
For the background- I'd just stick the entire row in either a linear or relative layout, then set a RoundedBitmapDrawable as the background of the layout. That will give you the rounded background effect. If necessary add some margin to the top and bottom of each view to increase the gap between items.
I suppose that you're using custom views for your listview's items, if so, I would set the background of the custom view to something like this:
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#color/white" />
<stroke android:width="4dp" android:color="#color/beige" /> //If you want a stroke
<corners
android:topLeftRadius="20dp"
android:topRightRadius="20dp"
android:bottomLeftRadius="20dp"
android:bottomRightRadius="20dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
As an alternate solution, I just got something working with CardViews and using Picasso with a CircleTransformation for the circle.
In this simple example, I used a RecyclerView of CardViews.
First, here is the CircleTransformation class that is used by Picasso:
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import com.squareup.picasso.Transformation;
public class CircleTransform implements Transformation {
#Override
public Bitmap transform(Bitmap source) {
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
Canvas canvas = new Canvas(bitmap);
BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG);
paint.setShader(shader);
float r = size/2f;
canvas.drawCircle(r, r, r-1, paint);
Paint paintBorder = new Paint();
paintBorder.setStyle(Style.STROKE);
paintBorder.setColor(Color.argb(84,0,0,0));
paintBorder.setAntiAlias(true);
paintBorder.setStrokeWidth(1);
canvas.drawCircle(r, r, r-1, paintBorder);
squaredBitmap.recycle();
return bitmap;
}
#Override
public String key() {
return "circle";
}
}
Here is the Fragment:
public class BlankFragment extends Fragment {
public BlankFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_blank, container, false);
RecyclerView rv = (RecyclerView) rootView.findViewById(R.id.rv_recycler_view);
rv.setHasFixedSize(true);
MyAdapter adapter = new MyAdapter(new String[]{"testone", "testtwo", "testthree", "testfour"}, getActivity());
rv.setAdapter(adapter);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
return rootView;
}
}
fragment_blank.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
The adapter, which includes the defaultCircleWithText() method for drawing the circle and text. Here I'm just using one color for the circles, but you can extend this to set the correct circle color for each row:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private String[] mDataset;
Context mContext;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class MyViewHolder extends RecyclerView.ViewHolder {
public CardView mCardView;
public TextView mTextView;
public ImageView mImageView;
public MyViewHolder(View v) {
super(v);
mCardView = (CardView) v.findViewById(R.id.card_view);
mTextView = (TextView) v.findViewById(R.id.tv_text);
mImageView = (ImageView) v.findViewById(R.id.iv_image);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset, Context context) {
mDataset = myDataset;
mContext = context;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_item, parent, false);
// set the view's size, margins, paddings and layout parameters
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.mTextView.setText(mDataset[position]);
Drawable drawable = new BitmapDrawable(mContext.getResources(), defaultCircleWithText("test"));
Picasso.with(mContext).load((String)null).fit().transform(new CircleTransform()).placeholder(drawable).into(holder.mImageView);
}
#Override
public int getItemCount() {
return mDataset.length;
}
public final static int BIG_IMAGE = 138;
public static Bitmap defaultCircleWithText(String text) {
int size = BIG_IMAGE;
Bitmap image = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(image);
int alpha = 165;
//hard-coded circle color:
int color = Color.argb(alpha,253,70,45);
Paint p_circle = new Paint();
p_circle.setAntiAlias(true);
p_circle.setColor(color);
c.drawCircle(size/2f, size/2f, size/2f-1, p_circle);
Paint p_text = new Paint();
p_text.setAntiAlias(true);
p_text.setColor(Color.WHITE);
p_text.setTextSize(58);
RectF bounds = new RectF(0, 0, c.getWidth(), c.getHeight());
// measure text width
bounds.right = p_text.measureText(text, 0, text.length());
// measure text height
bounds.bottom = p_text.descent() - p_text.ascent();
bounds.left += (c.getWidth() - bounds.right) / 2.0f;
bounds.top += (c.getHeight() - bounds.bottom) / 2.0f;
c.drawText(text, bounds.left, bounds.top - p_text.ascent(), p_text);
return image;
}
}
card_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="78dp" >
<android.support.v7.widget.CardView
android:id="#+id/card_view"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
card_view:cardCornerRadius="4dp"
android:layout_width="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="test" >
</TextView>
<ImageView
android:id="#+id/iv_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="10dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
Result:

Android: White on White Spinner

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.

Android GridView is empty

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

Android Gallery with first thumbnail as coverpage

Thanks for reading!
Some background:
I am building a Gallery app from the tutorial here
Only change I made to this code is to replace
i.setLayoutParams(new Gallery.LayoutParams(150, 100));
with
i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
to display only one gallery image at a time (Kinda like a slideshow viewer).
Problem:
I want the first thumbnail of the gallery to act as an Album Cover with two TextView's to display Album info.
Experiment:
So, I created an cover.xml like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:padding="6dip">
<ImageView android:id="#+cover/imgImage" android:adjustViewBounds="true"
android:layout_width="fill_parent" android:layout_height="fill_parent">
</ImageView>
<TextView android:id="#+cover/tvCoverText1"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:maxLines="2" android:text="Text1" />
<TextView android:id="#+cover/tvCoverText2"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:singleLine="true" android:maxLines="1" android:layout_below="#cover/tvCoverText1"
android:text="Text2" />
</RelativeLayout>
And here's the Java code. I check in getView() if the position is 0 (the first thumbnail) and then play around with the views.
package com.sagar.sample;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class Main extends Activity {
private LayoutInflater mInflater = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Gallery g = (Gallery) findViewById(R.main.gallery);
g.setAdapter(new ImageAdapter(this));
g.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
Toast.makeText(Main.this, "" + position, Toast.LENGTH_SHORT).show();
}
});
}
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
private Integer[] mImageIds = {
0, R.drawable.bp1, R.drawable.bp2, R.drawable.bp3
};
public ImageAdapter(Context c) {
mContext = c;
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// TypedArray a = obtainStyledAttributes(R.styleable.HelloGallery);
// mGalleryItemBackground = a.getResourceId(
// R.styleable.HelloGallery_android_galleryItemBackground, 0);
// a.recycle();
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
View view = convertView;
if(view == null) {
view = mInflater.inflate(R.layout.cover, null);
viewHolder = new ViewHolder();
viewHolder.tvCoverText1 = (TextView)view.findViewById(R.cover.tvCoverText1);
viewHolder.tvCoverText2 = (TextView)view.findViewById(R.cover.tvCoverText2);
viewHolder.imgView = (ImageView)view.findViewById(R.cover.imgImage);
view.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder)view.getTag();
}
if(position == 0) {
viewHolder.tvCoverText1.setVisibility(View.VISIBLE);
viewHolder.tvCoverText2.setVisibility(View.VISIBLE);
viewHolder.imgView.setVisibility(View.GONE);
}
else {
viewHolder.tvCoverText1.setVisibility(View.GONE);
viewHolder.tvCoverText2.setVisibility(View.GONE);
viewHolder.imgView.setVisibility(View.VISIBLE);
//viewHolder.imgView = new ImageView(mContext);
viewHolder.imgView.setImageResource(mImageIds[position]); //Album cover is at 0th position
viewHolder.imgView.setLayoutParams(new Gallery.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
viewHolder.imgView.setScaleType(ImageView.ScaleType.FIT_XY);
viewHolder.imgView.setBackgroundResource(mGalleryItemBackground);
}
return view;
}
}
static class ViewHolder {
TextView tvCoverText1, tvCoverText2;
ImageView imgView;
}
}
End Result:
When the app loads up, I first see a blank screen for a while and then the view changes to display the AlbumCover. And it's painfully slow to scroll across the images.
Hmm..obviously, I am doing something wrong. I sincerely hope someone could help me here :(
Thanks!
UPDATE: Adding main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<Gallery
android:id="#+main/gallery"
android:layout_width="fill_parent" android:layout_height="fill_parent"
/>
</RelativeLayout>
UPDATE2: So, here's some psuedo code to explain what I am trying to achieve:
if(position == 0)
//show toptext and bottomtext from cover.xml
else
//show tvTitle1 and tvTitle2 (may later include tvTitle3 and tvTitle4) from main.xml
Right now, only the position 0 case works and that too when I swipe to position 1 and swipe back to position 0 - the TextViews are grayed out and barely visible. :(
You need to set the text in your textviews everytime and not only when you inflate the view.
You should probably have 1 single layout file which holds the ui components in the gallery. Right now you have 2 TextView components which are independent of the Gallery. Instead, create some layout resource like this:
gallery_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="#+id/imageView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:adjustViewBounds="true"
android:background="#android:drawable/picture_frame"
android:layout_centerInParent="true" />
<TextView
android:id="#+main/tvTitle1" android:text="Title 1"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_above="#+main/tvTitle2">
</TextView>
<TextView
android:id="#+main/tvTitle2" android:text="Title 2"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentLeft="true">
</TextView>
</RelativeLayout>
So in your getView:
View v = convertView;
if(v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.gallery_item, null);
holder = new ViewHolder();
holder.text1 = (TextView)v.findViewById(R.id.tvTitle1);
holder.text2 = (TextView)v.findViewById(R.id.tvTitle2);
holder.imageView = (ImageView)v.findViewById(R.id.imageView);
v.setTag(holder);
}
else
holder = (ViewHolder)v.getTag();
if(position == 0) {
holder.text1.setVisibility(View.VISIBLE);
holder.text2.setVisibility(View.VISIBLE);
holder.imageView.setVisibility(View.GONE);
}
else {
holder.text1.setVisibility(View.GONE);
holder.text2.setVisibility(View.GONE);
holder.imageView.setVisibility(View.VISIBLE);
}
return v;
You may find that there is some strange behavior going on when you scroll through items, so you might have to directly access each UI component rather than using the holder:
((TextView)v.findViewById(R.id.tvTitle1)).setVisibility(View.GONE);, etc
You also may be interested in setting different types of views for getView: http://developer.android.com/reference/android/widget/Adapter.html#getItemViewType(int)
After trying all approaches suggested here, I wasn't able to still get a custom gallery the way I wanted it to. I kept running into ClassCastException. So, here's what worked for me till now. This is just a workaround and incase someone comes up with a better way to design a custom gallery - do post your answer here so I can accept it.
Thanks for helping out!

Categories

Resources