I have a ListPopupWindow that is being populated from a custom adapter. The custom xml consists of 2 textviews and a LinearLayout. The custom adapter populates the textviews and instantiates a custom view that draws a thumbnail sized vector based graphic. The custom view is then added to the Linear Layout.
The problem is that the first row displayed always has the wrong graphic displayed. It is sometimes the graphic from another row, sometimes half of it is the correct graphic, half from the wrong row. I've also noticed that if the list has enough rows in it to scroll, the items at the bottom of the list have the same problem when scrolling.
Has anyone else experienced this?
Custom List Adapter:
public class PageSearchListAdapter extends SimpleCursorAdapter
{
int _height = 130;
int _width = 130;
Cursor c;
Context context;
// Constructor, here we store any parameters we need in class variables
//
public PageSearchListAdapter(Context context,
int layout,
Cursor c,
String[] from,
int[] to)
{
super(context, layout, c, from, to);
this.c = c;
this.context=context;
}
// Main view method - the views in query_list_item are populated here
//
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
// Make sure we have a view to work with
//
if(convertView == null)
convertView = View.inflate(context, R.layout.query_list_item, null);
View row = convertView;
// go to the correct row in the cursor
//
c.moveToPosition(position);
// Get the views that need populating
//
TextView PageNum = (TextView) convertView.findViewById(R.id.Page_Num);
LinearLayout pic = (LinearLayout) convertView.findViewById(R.id.Page_Canvas);
TextView Date = (TextView) convertView.findViewById(R.id.Page_Date);
// Set the values
//
PageNum.setText(c.getString(c.getColumnIndex("PageNum")));
Date.setText(c.getString(c.getColumnIndex("Timestamp")));
List<Point> Vectors = new ArrayList<Point>();
byte[] asBytes = c.getBlob(c.getColumnIndex("Vectors"));
..
.. removed code to Convert Blob to array of 'Vector' records ...
..
// Draw the page
//
NotePadPage npPage = new NotePadPage(context, Vectors);
npPage.setLayoutParams(new LayoutParams(_width, _height));
pic.addView(npPage);
return(row);
}
}
NotePadPage class:
// Adapter to display a custom list item in a list view
//
public class NotePadPage extends View
{
int _height = 130;
int _width = 130;
Bitmap _bitmap;
Canvas _canvas;
Paint _paint;
List<Point> _Vectors = new ArrayList<Point>();
public NotePadPage(Context context, List<Point> Vectors)
{
super(context);
_Vectors = Vectors;
_paint = new Paint();
_paint.setColor(Color.WHITE);
_paint.setStyle(Paint.Style.STROKE);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
_height = View.MeasureSpec.getSize(heightMeasureSpec);
_width = View.MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(_width, _height);
_bitmap = Bitmap.createBitmap(_width, _height, Bitmap.Config.ARGB_8888);
_canvas = new Canvas(_bitmap);
}
#Override
protected void onDraw(Canvas canvas)
{
float yRatio = 1092/ _height;
float xRatio = 800 / _width;
Point lastPoint = null;
for (Point point : _Vectors)
{
switch (point.Type)
{
case Start:
{
lastPoint = point;
break;
}
case Midpoint:
case End:
{
canvas.drawLine(lastPoint.x / xRatio, lastPoint.y/ yRatio, point.x / xRatio, point.y/ yRatio, _paint);
lastPoint = point;
}
}
}
}
}
Referenced Classes:
public class Point
{
public float x, y;
public PointType Type;
}
public enum PointType
{
Start,
Midpoint ,
End;
}
XML for List row:
<?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:gravity="center_vertical|center_horizontal" >
<TextView
android:id="#+id/Page_Num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:layout_marginRight="5dp"
android:text="1"
android:textAppearance="?android:attr/textAppearanceMedium" />
<LinearLayout
android:id="#+id/Page_Canvas"
android:layout_width="130dip"
android:layout_height="130dip"
android:gravity="center_vertical|center_horizontal"
android:layout_toRightOf="#id/Page_Num">
</LinearLayout>
<TextView
android:id="#+id/Page_Date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:layout_marginLeft="5dp"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_toRightOf="#id/Page_Canvas">
</TextView>
</RelativeLayout>
Related
I want to dynamically create rectangle shape by using float values from server. The shapes should be precise like if any value is 25.2 and another is 25.3 then the 25.3 one should look bigger like we see in charts. So is there any way to achieve this? Here's the image:
I was trying to change the view size by using this:
itemView.tv_value.layoutParams = LinearLayout.LayoutParams(width,height)
But this seems to be accepting integer values only and if float converted to int using double then it will round off to the nearest number and it won't work.
How to achieve this either by using canvas or views?
First of all width or height of any view can not be float value.
You can set int value based on pixel of screen and float value ratio.
Layout for adapter to generate graph...
<?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="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="50dp"
android:layout_marginLeft="5dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_weight="0.8"
android:layout_height="wrap_content"
android:minHeight="50dp"
android:orientation="vertical"
android:gravity="center_vertical|center_horizontal|left"
android:id="#+id/lo_dynamic_view_container">
</LinearLayout>
<TextView
android:id="#+id/tv_chart_value"
android:layout_width="0dp"
android:layout_weight="0.2"
android:minHeight="50dp"
android:textColor="#000"
android:gravity="center_horizontal|center_vertical"
android:layout_height="match_parent"/>
</LinearLayout>
Generate Ration
private float getRatio(int width, float value, float highestValue){
float result = 0;
result = ( (float)width/highestValue) * value;
Log.e("Result", "width: "+ width +" "+(int) Math.floor(result)+"");
return result;
}
Combine Activity and adapter calss
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
ArrayList<Data> listData = new ArrayList<>();
BarChartAdapter barChartAdapter;
int[] colors = {Color.GREEN, Color.CYAN, Color.MAGENTA, Color.RED };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.rv_bar_chart);
listData.add(new Data(8.0f,Color.GREEN));
listData.add(new Data(4.0f,Color.CYAN));
listData.add(new Data(2.0f,Color.MAGENTA));
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
barChartAdapter = new BarChartAdapter(listData);
recyclerView.setAdapter(barChartAdapter);
}
public class BarChartAdapter extends RecyclerView.Adapter<BarChartAdapter.MyViewHolder> {
ArrayList<Data> listData = new ArrayList<>();
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
LinearLayout layout;
public MyViewHolder(View v) {
super(v);
textView = v.findViewById(R.id.tv_chart_value);
layout = (LinearLayout) v.findViewById(R.id.lo_dynamic_view_container);
}
}
public BarChartAdapter(ArrayList<Data> listData) {
this.listData = listData;
}
#Override
public BarChartAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
View v = (View) LayoutInflater
.from(parent.getContext())
.inflate(R.layout.barchart_layout, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.setIsRecyclable(false);
holder.textView.setText(listData.get(position).value+"");
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
width = width - (100/width)*80;
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
TextView tv = new TextView(MainActivity.this);
tv.setLayoutParams(lparams);
tv.setWidth((int) Math.floor( getRatio(width, listData.get(position).value,getHighestValue(listData))));
float redious [] = { 0, 0, 8.3f, 8.5f, 8.2f, 8.9f, 0, 0 };
ShapeDrawable shape = new ShapeDrawable (new RoundRectShape(redious,null,null));
shape.getPaint().setColor(listData.get(position).color);
//shape.getPaint().setColor(colors[new Random().nextInt((colors.length-1) - 0 + 1) + 0]);
//shape.getPaint().setColor(Color.GREEN);
tv.setBackground(shape);
holder.layout.addView(tv);
}
#Override
public int getItemCount() {
return listData.size();
}
}
private float getRatio(int width, float value, float highestValue){
float result = 0;
result = ( (float)width/highestValue) * value;
Log.e("Result", "width: "+ width +" "+(int) Math.floor(result)+"");
return result;
}
private float getHighestValue(ArrayList<Data> listData){
float result = 0.0f;
if(listData!=null){
if(listData.size()>0){
for (int i = 0; i < listData.size(); i++) {
result = listData.get(i).value>result?listData.get(i).value:result;
}
}
}
return result;
}
class Data{
float value;
int color;
public Data(float value, int color) {
this.value = value;
this.color = color;
}
}
}
Screen Shoot
Full Project link on GitHub
I am trying to set a dynamic width and height of my GridView's items, this is my code:
class GridAdapter extends BaseAdapter {
private Context context;
private GridAdapter(Context context, List<ParseObject> objects) {
super();
this.context = context;
}
// CONFIGURE CELL
#Override
public View getView(int position, View cell, ViewGroup parent) {
if (cell == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
cell = inflater.inflate(R.layout.cell_post_search, null);
}
//-----------------------------------------------
// MARK - INITIALIZE VIEWS
//-----------------------------------------------
ImageView postImg = cell.findViewById(R.id.cpsPostImg);
ImageView videoicon = cell.findViewById(R.id.cpsVideoIcon);
...
return cell;
}
#Override public int getCount() { return postsArray.size(); }
#Override public Object getItem(int position) { return postsArray.get(position); }
#Override public long getItemId(int position) { return position; }
}
// Set Adapter
postsGridView.setAdapter(new GridAdapter(ctx, postsArray));
// Set number of Columns accordingly to the device used
float scalefactor = getResources().getDisplayMetrics().density * screenW/3; // LET'S PRETEND MY screenW = 720, this value whoudl, be 240, which is the width i need for my cell
int number = getWindowManager().getDefaultDisplay().getWidth();
int columns = (int) ((float) number / scalefactor);
postsGridView.setNumColumns(columns);
Log.i(Configurations.TAG, "SCALE FACTOR: " + scalefactor);
And here's my custom cell_post_search.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/cpsCellLayout"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true">
<ImageView
android:id="#+id/cpsPostImg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="#c1c1c1"
android:scaleType="centerCrop"/>
<ImageView
android:id="#+id/cpsVideoIcon"
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_alignEnd="#+id/cpsPostImg"
android:layout_alignParentTop="true"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:visibility="invisible"
app:srcCompat="#drawable/play_butt"/>
<ImageView
android:id="#+id/cpsWhiteFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:srcCompat="#drawable/white_frame"/>
</RelativeLayout>
</RelativeLayout>
I get 480.0 as scale factor in my Logcat, which is not the right size I need (in my case it should be 240). Anyway, I've also tried to do this:
int columns = (int) ((float) number / (scalefactor/2));
So the scalefactor = 240, but it doesn't matter, because I need my cell's item to be square size, so basically: WIDTH = screenWidth/3, HEIGHT = screenWidth/3.
It doesn't work properly, my GridView shows 3 columns but cells get stretched in width - height looks fine - as shown here:
Is there a way to edit my code and make cells size correctly, as square images, 3 columns, based on the device size?
Try This
class GridAdapter extends BaseAdapter {
private Context context;
private GridAdapter(Context context, List<ParseObject> objects) {
super();
this.context = context;
}
// CONFIGURE CELL
#Override
public View getView(int position, View cell, ViewGroup parent) {
if (cell == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
cell = inflater.inflate(R.layout.cell_post_search, null);
}
//-----------------------------------------------
// MARK - INITIALIZE VIEWS
//-----------------------------------------------
ImageView postImg = cell.findViewById(R.id.cpsPostImg);
ImageView videoicon = cell.findViewById(R.id.cpsVideoIcon);
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) mContext).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;
postImg.getLayoutParams().height = width / 3;
...
return cell;
}
#Override public int getCount() { return postsArray.size(); }
#Override public Object getItem(int position) { return postsArray.get(position); }
#Override public long getItemId(int position) { return position; }
}
Also, in your XML layout, add android:numColumns="3":
<GridView
android:id="#+id/upPostsGridView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="3"/>
Background
I have a custom ViewGroup subclass that rotates and mirrors its child view. The purpose for this is to correctly display traditional Mongolian text.
I could put anything is this ViewGroup, but for my current project I am putting an EditText in it. (I was never successful in just rotating and mirroring the EditText directly. However, wrapping it in this custom view group does work.)
Problem
My problem is that when I try to resize the ViewGroup programmatically, its child view is not getting resized properly along with it. I would like the EditText to match the size of the parent ViewGroup so that it appears to be a single view.
MCVE
I made a new project to show the problem. The button increases the width of the ViewGroup (shown in red). The images show the project start (with everything working fine) and two width increments. The EditText is white and is not getting resized even though the width and height are set to match_parent
The full project code is below.
MongolViewGroup.java (Custom ViewGroup that rotates and mirrors its content)
public class MongolViewGroup extends ViewGroup {
private int angle = 90;
private final Matrix rotateMatrix = new Matrix();
private final Rect viewRectRotated = new Rect();
private final RectF tempRectF1 = new RectF();
private final RectF tempRectF2 = new RectF();
private final float[] viewTouchPoint = new float[2];
private final float[] childTouchPoint = new float[2];
private boolean angleChanged = true;
public MongolViewGroup(Context context) {
this(context, null);
}
public MongolViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
}
public View getView() {
return getChildAt(0);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final View view = getView();
if (view != null) {
measureChild(view, heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(resolveSize(view.getMeasuredHeight(), widthMeasureSpec),
resolveSize(view.getMeasuredWidth(), heightMeasureSpec));
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if (angleChanged) {
final RectF layoutRect = tempRectF1;
final RectF layoutRectRotated = tempRectF2;
layoutRect.set(0, 0, right - left, bottom - top);
rotateMatrix.setRotate(angle, layoutRect.centerX(), layoutRect.centerY());
rotateMatrix.postScale(-1, 1);
rotateMatrix.mapRect(layoutRectRotated, layoutRect);
layoutRectRotated.round(viewRectRotated);
angleChanged = false;
}
final View view = getView();
if (view != null) {
view.layout(viewRectRotated.left, viewRectRotated.top, viewRectRotated.right,
viewRectRotated.bottom);
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
canvas.save();
canvas.rotate(-angle, getWidth() / 2f, getHeight() / 2f);
canvas.scale(-1, 1);
super.dispatchDraw(canvas);
canvas.restore();
}
#Override
public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
invalidate();
return super.invalidateChildInParent(location, dirty);
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
viewTouchPoint[0] = event.getX();
viewTouchPoint[1] = event.getY();
rotateMatrix.mapPoints(childTouchPoint, viewTouchPoint);
event.setLocation(childTouchPoint[0], childTouchPoint[1]);
boolean result = super.dispatchTouchEvent(event);
event.setLocation(viewTouchPoint[0], viewTouchPoint[1]);
return result;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
MongolViewGroup viewGroup;
EditText editText;
int newWidth = 300;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewGroup = (MongolViewGroup) findViewById(R.id.viewGroup);
editText = (EditText) findViewById(R.id.editText);
}
public void buttonClicked(View view) {
newWidth += 200;
ViewGroup.LayoutParams params = viewGroup.getLayoutParams();
params.width=newWidth;
viewGroup.setLayoutParams(params);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
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="com.example.mongolviewgrouptest.MainActivity">
<com.example.mongolviewgrouptest.MongolViewGroup
android:id="#+id/viewGroup"
android:layout_width="100dp"
android:layout_height="200dp"
android:background="#color/colorAccent">
<EditText
android:id="#+id/editText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#android:color/black"
android:background="#android:color/white"/>
</com.example.mongolviewgrouptest.MongolViewGroup>
<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/button"
android:onClick="buttonClicked"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
You're not recalculating viewRectRotated for your EditText when the
ViewGroup's onLayout(...) method is called again.
Since angleChanged is set to false (and never changes) after your ViewGroups first layout, then the part that calculates the left, right, top and bottom values for your EditText
is skipped any time after the first time when your ViewGroup
requestsLayout (when you change its height or width).
As such, your EditText is still laid out with the same left,right,top
and bottom values it was initially laid out with.
Do away with the angleChanged and it should work just fine. Like so:
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
final RectF layoutRect = tempRectF1;
final RectF layoutRectRotated = tempRectF2;
layoutRect.set(0, 0, right - left, bottom - top);
rotateMatrix.setRotate(angle, layoutRect.centerX(), layoutRect.centerY());
rotateMatrix.postScale(-1, 1);
rotateMatrix.mapRect(layoutRectRotated, layoutRect);
layoutRectRotated.round(viewRectRotated);
final View view = getView();
if (view != null) {
view.layout(viewRectRotated.left, viewRectRotated.top, viewRectRotated.right,
viewRectRotated.bottom);
}
}
I've tested this and it works just fine this way.
If you need angleChanged for any reason, then just make sure it's changed back to true inside your ViewGroup's onMeasure method so that viewRectRotated is recalculated again. However I wouldn't recommend that.
I have Staggered Grid view in which each item contains an image and text. Have a look at this
Below code is item layout xml. DynamicHeightImageView is extended ImageView which is use to change height of image. Here I have tried to set
android:layout_width="fill_parent"
But I think it is not working.
<?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="#drawable/background_card"
android:orientation="vertical" >
<com.etsy.android.grid.util.DynamicHeightImageView
android:id="#+id/image"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher"
android:gravity="center" />
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="4dp"
android:paddingLeft="8dp"
android:textColor="#ED430F"
android:paddingRight="8dp"
android:paddingTop="4dp"
android:textSize="15sp"
android:typeface="sans" />
<TextView
android:id="#+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:paddingBottom="8dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingTop="4dp"
android:textSize="12sp"
android:textColor="#848484"
android:textStyle="italic" />
</LinearLayout>
DynamicHeightImageView class has following code
public class DynamicHeightImageView extends ImageView {
private double mHeightRatio;
public static float radius = 2.0f;
Path clipPath = new Path();
RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight());
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public DynamicHeightImageView(Context context, AttributeSet attrs) {
super(context, attrs);
if (Build.VERSION.SDK_INT < 18) {
this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public DynamicHeightImageView(Context context) {
super(context);
if (Build.VERSION.SDK_INT < 18) {
this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
}
public void setHeightRatio(double ratio) {
if (ratio != mHeightRatio) {
mHeightRatio = ratio;
requestLayout();
}
}
public double getHeightRatio() {
return mHeightRatio;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mHeightRatio > 0.0) {
// set the image views size
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = (int) (width * mHeightRatio);
setMeasuredDimension(width, height);
}
else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
#Override
protected void onDraw(Canvas canvas) {
rect.left = 0;
rect.top = 0;
rect.right = this.getWidth();
rect.bottom = this.getHeight();
clipPath.addRoundRect(rect, radius, radius, Path.Direction.CW);
canvas.clipPath(clipPath);
super.onDraw(canvas);
}
}
Below code is Grid View Adapter class. This actually binds data with GridView. Here I have also tried to set image view width to fill the parent but it is not working result is the same. Can anyone tel me where I am making mistake?
public class DataAdapter extends ArrayAdapter<Video> {
Activity activity;
int resource;
List<Video> datas;
public DataAdapter(Activity activity, int resource, List<Video> objects) {
super(activity, resource, objects);
this.activity = activity;
this.resource = resource;
this.datas = objects;
}
#SuppressWarnings("deprecation")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
final DealHolder holder;
if (row == null) {
LayoutInflater inflater = activity.getLayoutInflater();
row = inflater.inflate(resource, parent, false);
holder = new DealHolder();
holder.image = (DynamicHeightImageView)row.findViewById(R.id.image);
holder.title = (TextView)row.findViewById(R.id.title);
holder.date = (TextView)row.findViewById(R.id.description);
row.setTag(holder);
}
else {
holder = (DealHolder) row.getTag();
}
final Video data = datas.get(position);
Picasso.with(this.getContext())
.load(data.getImgURL())
.into(holder.image);
holder.image.setHeightRatio(getRandomHeight());
holder.image.getLayoutParams().width = LayoutParams.FILL_PARENT;
holder.image.requestLayout();
holder.title.setText(data.getTitle());
holder.date.setText(data.getUploadedDate().toGMTString().subSequence(0, 16));
return row;
}
static class DealHolder {
DynamicHeightImageView image;
TextView title;
TextView date;
}
private float getRandomHeight(){
ArrayList<Float> lista = new ArrayList<Float>();
lista.add((float) 0.5);
lista.add((float) 1.0);
lista.add((float) 0.75);
lista.add((float) 1.5);
Collections.shuffle(lista);
return lista.get(0);
}
}
I'm building an app that has a mini slotMachine game inside. The problem is that I use a GridView for each column of the slot and for some devices (not all) the first symbol of the slot has a space above that comes from nowhere...
The table of the slot is 3 rows X 5 columns.
The space doesn't come from the calculation of the symbol width and height because I've found that with two devices withe perfectly identical resolution and density (Galaxy tab 10.1 and Galaxy note 10.1) the spacing is different: 0 for one and 5 for the other.
Any help?
My MainActivity:
public class MainActivity extends Activity{
SlotView slot;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
slot=new SlotView(this);
slot.refreshSlotView("AAAAAAAAAAAAAAA");
}
}
SlotView:
public class SlotView {
private ArrayList<GridAdapter> adapter=new ArrayList<GridAdapter>();
public float H_RATIO=2/3; //height ratio of the grid based on the device
public float W_RATIO=5/6; //width ratio of the grid based on the device
Activity activity;
String path = "file:///android_asset/Slot/Slot-";
public SlotView(Context c){
activity = (Activity) c;
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
final int hDisplay=dm.heightPixels;
int wImage=(1024*hDisplay)/768; //width of the central image
float heightGrid=(hDisplay*2)/3; //grid height
float widthGrid=((wImage*5)/6); //grid width
float heightSymbol=(heightGrid-(8))/3; // symbol height (3 symbols for column with a spacing of 4 px)
//relative layout for the container table
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams((int)widthGrid, (int)heightGrid);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
// grid of the slot
LinearLayout grid_layout=(LinearLayout)activity.findViewById(R.id.layout_grid);
grid_layout.setLayoutParams(params);
grid_layout.setGravity(Gravity.TOP);
// gridview of the columns
LinearLayout.LayoutParams params_grid=new LinearLayout.LayoutParams((int)heightSymbol, (int)heightGrid);
for(int i=0; i<5; i++){ // five columns
GridView slot=new GridView(activity);
slot.setScrollContainer(false);
slot.setVerticalScrollBarEnabled(false);
slot.setHorizontalScrollBarEnabled(false);
if(i<4) {
params_grid.setMargins(0,0,4,0); // spacing between each column
}
slot.setLayoutParams(params_grid);
slot.setVerticalSpacing(4);
slot.setPadding(0, 0, 0, 0);
slot.setColumnWidth((int)heightSymbol);
slot.setNumColumns(GridView.AUTO_FIT);
slot.setGravity(Gravity.CENTER);
GridAdapter grid_adapter=new GridAdapter(activity, (int)heightSymbol, (int)heightSymbol);
adapter.add(grid_adapter);
slot.setAdapter(grid_adapter);
grid_layout.addView(slot);
}
}
public void refreshSlotView(String configTris){
for(int pos=0; pos<5; pos++){
String[] mThumbIds=new String[3];
int z=0;
for(int i=pos; z<3 && i<configTris.length(); i=i+5){
char letter=configTris.charAt(i);
mThumbIds[z]=path + letter + ".png";
z++;
}
adapter.get(pos).setArrayOfImage(mThumbIds);
adapter.get(pos).notifyDataSetChanged();
}
}
}
The adapter:
public class GridAdapter extends BaseAdapter {
private Context mContext;
private String[] mThumbIds={};
private int w;
private int h;
public GridAdapter(Context c, int w, int h) {
mContext = c;
this.w=w;
this.h=h;
}
public int getCount() {
return mThumbIds.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
View view=convertView;
ImageView imageView;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.slot_element, null);
RelativeLayout rel=(RelativeLayout)view.findViewById(R.id.rel);
rel.setLayoutParams(new GridView.LayoutParams(w, h));
imageView=(ImageView)view.findViewById(R.id.image);
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(w, h);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
imageView.setLayoutParams(params);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
}else{
imageView = (ImageView) view.findViewById(R.id.image);
}
Picasso.with(mContext).load(mThumbIds[position]).into(imageView); // puts the image in the imageview
return view;
}
public void setArrayOfImage(String[] images){
this.mThumbIds=images;
}
public void showSymbolAtIndex(char letter, int position){
mThumbIds[position]="file:///android_asset/" + "Slot/Slot-" + letter + ".png";
notifyDataSetChanged();
}
}
This is the MainActivity Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/layout_grid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="horizontal" >
</LinearLayout>
</RelativeLayout>
And the slot_element Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rel"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY" />
</RelativeLayout>
Now that's the result:
And that's the proof of the existing spacing (if I drag one of the columns up):