Trying to build a simple grid with views I create. The views will look like dominos this is the class that defines them that extends view
public class Domino extends View{
private Paint paint;
public Domino(Context context) {
super(context);
init();
}
public void init(){
paint = new Paint();
paint.setTextSize(12);
paint.setColor(0xFF668800);
paint.setStyle(Paint.Style.FILL);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
invalidate();
}
}
And then in an array adapter I try to build them like this
private class CustomAdapter extends ArrayAdapter<String> {
private Context mContext;
private int tileW, tileH;
private List<String> list = new ArrayList<String>();
public CustomAdapter(Context context, int textViewResourceId, List<String> objects) {
super(context, textViewResourceId, objects);
this.mContext = context;
this.list = objects;
// we need to do some calculation to get accurate screen dimensions if we're going fullscreen
DisplayMetrics displayMetrics = new DisplayMetrics();
((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics);
this.tileW = displayMetrics.widthPixels / 4;
this.tileH = tileW/2;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Domino domino;
if (convertView == null) {
// if it's not recycled, initialize some attributes
domino = new Domino(mContext);
domino.setLayoutParams(new GridView.LayoutParams(this.tileW, this.tileH));
domino.measure(this.tileW, this.tileH);
}
else {
domino = (Domino) convertView;
}
String colorString = list.get(position);
int rid = 0;
// figure out what color we're going to use
if (colorString.equals("r")) {
rid = R.drawable.grid_red;
}
else if (colorString.equals("o")) {
rid = R.drawable.grid_orange;
}
else if (colorString.equals("y")) {
rid = R.drawable.grid_yellow;
}
else if (colorString.equals("g")) {
rid = R.drawable.grid_green;
}
else if (colorString.equals("b")) {
rid = R.drawable.grid_blue;
}
else if (colorString.equals("i")) {
rid = R.drawable.grid_indigo;
}
else if (colorString.equals("v")) {
rid = R.drawable.grid_violet;
}
else {
rid = R.color.black;
}
return domino;
}
}
But I dont see anything, I want to programmatically set the height and width in the array adapter. What am i missing?
// Replace this piece of code see what happens.
if (convertView == null) {
// if it's not recycled, initialize some attributes
domino = new Domino(mContext);
domino.setLayoutParams(new GridView.LayoutParams(this.tileW, this.tileH));
domino.measure(this.tileW, this.tileH);
convertView.setTag(domino);
} else {
domino = (Domino) convertView.getTag();
}
Related
I just followed this tutorial, to create a custom View as an item of a GridLayout.
That's my CustomView
public class RowView extends View{
boolean touchOn;
boolean mDownTouch = false;
private OnToggledListener toggledListener;
int _IdRow = 0;
int _IdColumn = 0;
public RowView(Context context, int Rows, int Columns) {
super(context);
this._IdRow = Rows;
this._IdColumn = Columns;
init();
}
public RowView(Context context) {
super(context);
init();
}
public RowView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RowView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
touchOn = false;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
}
#Override
protected void onDraw(Canvas canvas) {
if (touchOn) {
canvas.drawColor(Color.RED);
} else {
canvas.drawColor(Color.GRAY);
}
}
//onClick not possible to use on custom View so, onTouchEvent is the solution
#Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
//if Click
case MotionEvent.ACTION_DOWN:
touchOn = !touchOn;
invalidate();
if(toggledListener != null){
toggledListener.OnToggled(this, touchOn);
}
mDownTouch = true;
return true;
case MotionEvent.ACTION_UP:
if (mDownTouch) {
mDownTouch = false;
performClick();
return true;
}
}
return false;
}
#Override
public boolean performClick() {
super.performClick();
return true;
}
public void setOnToggledListener(OnToggledListener listener){
toggledListener = listener;
}
public int get_IdRow() {
return _IdRow;
}
public int get_IdColumn() {
return _IdColumn;
}
On this class I can detect when user clicks on an item of GridLayout and change it to another color, that's ok.
But the problem comes at the time to create this :
This is my MainActivity where I show the GridLayout :
int numOfCol = mGridLayout.getColumnCount();
int numOfRow = mGridLayout.getRowCount();
mRowViews = new RowView[numOfCol*numOfRow];
for(int yPos=0; yPos<numOfRow; yPos++){
for(int xPos=0; xPos<numOfCol; xPos++){
RowView tView = new RowView(this, xPos, yPos);
tView.setOnToggledListener(this);
mRowViews[yPos*numOfCol + xPos] = tView;
mGridLayout.addView(tView);
}
}
mGridLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){
#Override
public void onGlobalLayout() {
final int MARGIN = 5;
int pWidth = mGridLayout.getWidth();
int pHeight = mGridLayout.getHeight();
int numOfCol = mGridLayout.getColumnCount();
int numOfRow = mGridLayout.getRowCount();
int w = pWidth/numOfCol;
int h = pHeight/numOfRow;
for(int yPos=0; yPos<numOfRow; yPos++){
for(int xPos=0; xPos<numOfCol; xPos++){
GridLayout.LayoutParams params =
(GridLayout.LayoutParams)mRowViews[yPos*numOfCol + xPos].getLayoutParams();
params.width = w - 2*MARGIN;
params.height = h - 2*MARGIN;
params.setMargins(MARGIN, MARGIN, MARGIN, MARGIN);
mRowViews[yPos*numOfCol + xPos].setLayoutParams(params);
}
}
}});
Also there is a method of the Interface OnToggledListener that gives to me the row and column of my GridLayout when an item of it is clicked :
#Override
public void OnToggled(MyView v, boolean touchOn) {
//get the id string
String idString = v.get_IdRow() + ":" + v.get_IdColumn();
}
I'd like to avoid to create that mGridLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() because it fills on the screen thing that I don't want... I tried to put GridLayout 6x6 with android:layout_height="400dp" and it only show 3x3 and this is the LogCat message
D/android.widget.GridLayout: vertical constraints: y6-y0>=1749, y6-y5<=291, y5-y4<=291, y4-y3<=291, y3-y2<=291, y2-y1<=291, y1-y0<=291 are inconsistent; permanently removing: y6-y5<=291.
I'd like to do something like GridLayout[row][colum] to get the color of background and then do stuff, but I'm not able to find this solution.
For simplifying, you can implement a custom Board view wrapping the GridLayout and related logic. Below I report a possible approach.
Expectation here is to have an ItemView for representing one single cell in the board.
public class Board extends FrameLayout implements View.OnClickListener {
private GridLayout mGridView;
private int mRowsCount;
private int mColsCount;
private int mCellSpace;
private OnItemClickListener mOnItemClickListener;
public Board(Context context) {
super(context);
init(context, null);
}
// other constructors
private void init(Context context, AttributeSet attrs) {
// default values
mRowsCount = 1;
mColsCount = 1;
View layout = inflate(getContext(), R.layout.view_lights_board, null);
mGridView = (GridLayout) layout.findViewById(R.id.view_grid);
mGridView.setRowCount(mRowsCount);
mGridView.setColumnCount(mColsCount);
mGridView.post(new Runnable() {
#Override
public void run() {
int width = getMeasuredWidth() / getColumnsCount();
int height = getMeasuredHeight() / getRowsCount();
for (int i = 0; i < getRowsCount(); i++) {
for (int j = 0; j < getColumnsCount(); j++) {
GridLayout.LayoutParams params = (GridLayout.LayoutParams)
getChildAt(i, j).getLayoutParams();
params.width = width;
params.height = height;
getChildAt(i, j).setLayoutParams(params);
}
}
}
});
addView(layout);
}
// this method allows to dinamically create grid
public void buildChildren(int rowsCount, int colsCount) {
mRowsCount = rowsCount;
mColsCount = colsCount;
mGridView.setRowCount(mRowsCount);
mGridView.setColumnCount(mColsCount);
buildChildren();
}
public void buildChildren() {
for (int i = 0; i < getRowsCount(); i++) {
for (int j = 0; j < getColumnsCount(); j++) {
ItemView view = new ItemView(getContext(), i, j);
view.setOnClickListener(this);
mGridView.addView(view);
}
}
}
public void setOnItemClickListener(OnItemClickListener listener) {
mOnItemClickListener = listener;
}
public ItemView getChildAt(int rowIndex, int columnIndex) {
int index = (getColumnsCount() * rowIndex) + columnIndex;
return (ItemView) mGridView.getChildAt(index);
}
public boolean isTouchOn(int rowIndex, int columnIndex) {
return getChildAt(rowIndex, columnIndex).isTouchOn();
}
public int getColumnsCount() {
return mGridView.getColumnCount();
}
public int getRowsCount() {
return mGridView.getRowCount();
}
#Override
public void onClick(View v) {
if (v instanceof ItemView) {
ItemView view = (ItemView) v;
if (mOnItemClickListener != null) {
mOnItemClickListener.onItemClick(view);
}
}
}
public interface OnItemClickListener {
void onItemClick(ItemView view);
}
}
In your Activity layout you will have something like this (here I assume your app package is com.android.example):
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.android.example.Board
android:id="#+id/grid"
android:layout_width="match_parent"
android:layout_height="400dp" />
</FrameLayout>
And this is possible implementation of the Activity:
public class MainActivity extends AppCompatActivity implements LightsOutBoard.OnItemClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Board board = (Board) findViewById(R.id.grid);
board.setOnItemClickListener(this);
board.buildChildren(3, 3);
}
#Override
public void onItemClick(ItemView view) {
String text = view.getRowIndex() + " - " + view.getColumnIndex();
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
}
Hope this could help.
My app contains two ExpandableHeightListViews and one ExpandableHeightGridView with shared vertical scrolling.
The contents of the views are read in from a file. This works fine with small files, the data is displayed correctly and the activity loads.
However, when selecting large files, the activity never actually loads, when I debug it, the adapters for the three views are just looping round endlessly. I'm assuming this is due to the expanded nature of the views they are trying to load everything, but surely this can be avoided?
Here is the code ...
ExpandableHeightListView ...
public class ExpandableHeightListView extends ListView
{
boolean expanded = false;
public ExpandableHeightListView(Context context)
{
super(context);
}
public ExpandableHeightListView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ExpandableHeightListView(Context context, AttributeSet attrs, int defaultStyle)
{
super(context, attrs, defaultStyle);
}
public boolean isExpanded()
{
return expanded;
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// HACK! TAKE THAT ANDROID!
if (isExpanded())
{
// Calculate entire height by providing a very large height hint.
// View.MEASURED_SIZE_MASK represents the largest height possible.
int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
else
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void setExpanded(boolean expanded)
{
this.expanded = expanded;
}
}
ExpandableHeightGridView ...
public class ExpandableHeightGridView extends GridView
{
boolean expanded = false;
public ExpandableHeightGridView(Context context)
{
super(context);
}
public ExpandableHeightGridView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ExpandableHeightGridView(Context context, AttributeSet attrs,
int defStyle)
{
super(context, attrs, defStyle);
}
public boolean isExpanded()
{
return expanded;
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// HACK! TAKE THAT ANDROID!
if (isExpanded())
{
// Calculate entire height by providing a very large height hint.
// View.MEASURED_SIZE_MASK represents the largest height possible.
int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
else
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void setExpanded(boolean expanded)
{
this.expanded = expanded;
}
}
MainActivity ...
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView (R.layout.activity_editor);
Intent intent = getIntent();
m_File = new File (intent.getStringExtra ("file_path"));
m_FileLength = (int) m_File.length();
// Account for non-complete line at end of file ...
if ((m_FileLength % 8) == 0)
m_NumLines = (m_FileLength / 8) + ADDITIONAL_LINES;
else
m_NumLines = (m_FileLength / 8) + ADDITIONAL_LINES + 1;
// Set up index ListView
m_IndexListView = (ExpandableHeightListView) findViewById (R.id.index_listview);
m_IndexAdapter = new IndexAdapter (getApplicationContext(), m_NumLines);
m_IndexListView.setAdapter (m_IndexAdapter);
m_IndexListView.setExpanded(true);
// File reader object for hex/ascii adapters ...
FileReader fileReader = new FileReader (getApplicationContext(), m_File);
// Set up hex GridView
m_HexGridView = (ExpandableHeightGridView) findViewById (R.id.hex_gridview);
m_HexAdapter = new HexAdapter (getApplicationContext(), fileReader);
m_HexGridView.setAdapter(m_HexAdapter);
m_HexGridView.setExpanded (true);
// Set up ascii ListView
m_AsciiListView = (ExpandableHeightListView) findViewById (R.id.ascii_listview);
m_AsciiAdapter = new AsciiAdapter (getApplicationContext(), m_NumLines, fileReader);
m_AsciiListView.setAdapter(m_AsciiAdapter);
m_AsciiListView.setExpanded (true);
m_HexGridView.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
view.setSelected (true);
}
});
The three adapters simply read some data from the given file and display it accordingly.
Does anyone know how to fix this and make the adapter views only load the necessary part?
EDIT: Adapter code ...
HexAdapter ...
public class HexAdapter extends BaseAdapter
{
// CONSTANTS
// Number of additional blank lines to append ...
private final int ADDITIONAL_LINES = 30;
// VARIABLES
// Context of the EditorActivity ...
private Context m_Context;
// Reference to file being edited ...
private FileReader m_FileReader;
// Number of elements that are within file ...
private int m_FileLength;
// Number of total elements to produce ...
private int m_NumElements;
// FUNCTIONS
public HexAdapter (Context c, FileReader fileReader)
{
m_Context = c;
m_FileReader = fileReader;
m_FileLength = (int) m_FileReader.getLength();
int finishLine = 8 - (m_FileLength % 8);
m_NumElements = m_FileLength + finishLine + (ADDITIONAL_LINES * 8);
}
public int getCount()
{
return m_NumElements;
}
public Object getItem(int position)
{
return null;
}
public long getItemId(int position)
{
return 0;
}
// Create new TextView for each item referenced by the Adapter ...
public View getView(int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = (LayoutInflater)
m_Context.getSystemService (Context.LAYOUT_INFLATER_SERVICE);
View view;
if (null == convertView)
view = inflater.inflate (R.layout.editor_hex_element, parent, false);
else
view = convertView;
// Remove padding if rightmost element ...
LinearLayout container = (LinearLayout) view.findViewById (R.id.gridview_hex_container);
if ((position % 8) == 7)
container.setPadding (0,0,0,0);
else
container.setPadding (0,0,1,0);
String hexText;
// If position is within current file space, read from file ...
if (position < m_FileLength)
{
// Read from file and generate hexadecimal text
byte[] buffer = m_FileReader.ReadBytesFromFile(position, 1);
hexText = Integer.toHexString ((char)buffer[0]).toUpperCase();
// Prepend extra zero if length is 1 ...
if (hexText.length() == 1)
hexText = "0" + hexText;
}
else
{
// Set to default un-edited value (00) ...
hexText = "00";
}
// Get TextView instance and set text ...
TextView textView = (TextView) view.findViewById (R.id.gridview_hex_edit);
textView.setText (hexText);
// Set colour depending on file length ...
if (position < m_FileLength)
textView.setTextColor (m_Context.getResources ().getColor (R.color.DarkerAccentOrange));
else
textView.setTextColor (m_Context.getResources ().getColor (R.color.hex_gray));
return view;
}
// TODO: Add function to update file length and numElements variables
// public void UpdateFileLength (int numLength) ...
}
AsciiAdapter ...
public AsciiAdapter (Context c, int numLines, FileReader fileReader)
{
m_Context = c;
m_FileReader = fileReader;
m_NumLines = numLines;
m_FileLength = (int) fileReader.getLength();
}
public int getCount()
{
return m_NumLines;
}
public Object getItem(int position)
{
return null;
}
public long getItemId(int position)
{
return 0;
}
// Create new TextView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = (LayoutInflater)
m_Context.getSystemService (Context.LAYOUT_INFLATER_SERVICE);
View view;
if (null == convertView)
view = inflater.inflate (R.layout.editor_ascii_element, parent, false);
else
view = convertView;
final int readPosition = position * BYTE_SIZE;
final int fileRemaining = m_FileLength - readPosition;
final int readLength = (fileRemaining >= BYTE_SIZE) ? BYTE_SIZE : fileRemaining;
byte[] buffer;
StringBuilder builder = new StringBuilder ();
// If some of file remaining, read ...
if (readLength > 0)
{
buffer = m_FileReader.ReadBytesFromFile (readPosition, readLength);
// Build read string ...
for (byte b : buffer)
builder.append (convertByte (b));
}
// Append remaining part of string (not read from file) ...
final int remaining = (readLength > 0) ? (BYTE_SIZE - readLength) : BYTE_SIZE;
for (int k = 0; k < remaining; k++)
builder.append ('.');
TextView textView = (TextView) view.findViewById (R.id.ascii_textview);
textView.setText (builder.toString());
return view;
}
}
I am loading remote image into row of listView using picaso callback. But image changes multiple times when listView is scrolled very fast. I guess its due to row reuse. How can I correct it and show correct image without reloading of different images in imageView.
I also setting null bitmap into ImageView. So that it doesn't use previous image while reusing image
Here is My Code:
#Override
public View getView(int position, View convertView, ViewGroup arg2)
{
ViewHolder holder = null;
if (convertView == null)
{
LayoutInflater vi = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.row_health, arg2, false);
holder = new ViewHolder();
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
holder.imageOfDoctor_select.setImageBitmap(null);
}
loadImage("imageViewURL", relLyt_txtPicInitials, imgVw);
}
private void loadImage(String imgURL, RoundedImage imgVw, RelativeLayout relLyt_txtPicInitials){
Target target = new Target() {
#Override
public void onBitmapFailed(Drawable arg0)
{
// TODO Auto-generated method stub
}
#Override
public void onPrepareLoad(Drawable arg0)
{
// TODO Auto-generated method stub
}
#Override
public void onBitmapLoaded(Bitmap bitmap, LoadedFrom arg1)
{
if(bitmap != null){
imgVw.setVisibility(View.VISIBLE);
imgVw.setImageBitmap(bitmap);
relLyt_txtPicInitials.setVisibility(View.GONE);
}
}
};
if (!TextUtils.isEmpty(imgURL) && !imgURL.equalsIgnoreCase("null") && URLUtil.isValidUrl(imgURL))
{
Picasso.with(context).load(imgURL).into(target);
}
}
RoundedImage.java
public class RoundedImage extends ImageView
{
private float cornerRadius;
private float bitmapCornerRadius;
public RoundedImage(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
getXMLAttribute(context, attrs);
// TODO Auto-generated constructor stub
}
public RoundedImage(Context context, AttributeSet attrs)
{
super(context, attrs);
getXMLAttribute(context, attrs);
// TODO Auto-generated constructor stub
}
public RoundedImage(Context context)
{
super(context);
// TODO Auto-generated constructor stub
}
#Override
public void setImageBitmap(Bitmap bm)
{
if (bm != null)
{
bm = Utils.getRoundedCornerBitmap(bm, 50);
}
super.setImageBitmap(bm);
}
private void getXMLAttribute(Context context, AttributeSet attrs)
{
// Get proportion.
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundedCornerImageView);
cornerRadius = a.getDimension(R.styleable.RoundedCornerImageView_cornerRadius, 0);
a.recycle();
}
public void setCornerRadius(int radius)
{
this.cornerRadius = radius;
}
#Override
protected void onDraw(Canvas canvas)
{
boolean applyCornerToBitmap = false;
Drawable drawable = getDrawable();
if (drawable != null)
{
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
if (bitmap != null)
{
int viewWidth = getWidth();
if (viewWidth != 0f)
{ // Only round the corner if view width is not zero.
// Calculate the corner radius on the real bitmap, based on
// the
// corner radius of the view.
int bitmapWidth = bitmap.getWidth();
float newBitmapCornerRadius = cornerRadius * bitmapWidth / viewWidth;
// If newBitmapCornerRadius equals to bitmapCornerRadius,
// then it is not needed to set the round the corner bitmap
// to the drawable again.
if (bitmapCornerRadius != newBitmapCornerRadius)
{
applyCornerToBitmap = true;
// Create bitmap with rounded corner.
int bitmapHeight = bitmap.getHeight();
bitmapCornerRadius = newBitmapCornerRadius;
bitmap = Utils.getRoundedCornerBitmap(bitmap, 50);
// Set rounded corner bitmap to the view's drawable.
setImageBitmap(bitmap); // This will call onDraw()
// again.
}
}
}
}
// Call super onDraw() if the drawable has already been rounded.
if (!applyCornerToBitmap)
{
super.onDraw(canvas);
}
}
}
Modify like this, you guessed right, issue is related to views recycling, and in every getView method, all images must clear, for example set placeholder or set null, I don't know exactly imgVw or holder.imageOfDoctor_select must reset, try them both
How can I correct it and show correct image without reloading of different images in imageView.
You can't, because ImageView still holds previous image
#Override
public View getView(int position, View convertView, ViewGroup arg2) {
ViewHolder holder = null;
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.row_health, arg2, false);
holder = new ViewHolder();
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.imageOfDoctor_select.setImageBitmap(null); //Or put placeholder here, until image loaded
loadImage("imageViewURL", relLyt_txtPicInitials, imgVw);
}
I can suggerst an another solution, without a target, just use public void into(android.widget.ImageView target, com.squareup.picasso.Callback callback) this overload similar this
Picasso.with(getContext())
.load(imgVw)
.into(imgVw, new Callback() {
#Override
public void onSuccess() {
imgVw.setVisibility(View.VISIBLE);
relLyt_txtPicInitials.setVisibility(View.GONE);
}
#Override
public void onError() {
}
});
I have a ListView in which there is a TextView and a custom view in which I am drawing a rectangle. I want a functionality that when a row of ListView is clicked, the rectangle should become bigger but other row's rectangle should remain in its previous shape.
So first I am increasing width and height of layout and then trying to increase the rectangle size after that but although my onDraw() method is called when I am clicking the listener but size of rectangle is not increasing.
Also my onDraw() method of DrawView is called infinitely even though I am clicking only once
Can anyone help me out.
DrawView.java, which is used for making making rectangle
public class DrawView extends View {
Paint paint = new Paint();
public int x=-1; // this variable will tell
public DrawView(Context context) {
this(context, null);
}
public DrawView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onDraw(Canvas canvas) {
paint.setStrokeWidth(10);
paint.setColor(Color.MAGENTA);
Log.e("Ronak","onDraw "+x);
canvas.drawRect(0, 0, 300, 200, paint );
if(x>=0) //this method is not called for first view but is called for onClickListener
{
increase(canvas);
}
}
private void increase(Canvas canvas) {
Log.e("Ronak","Increase");
canvas.drawRect(0, 0, 700, 800, paint );
}
}
My getView() function for custom ListView
public View getView(final int position, View convertView, final ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.news_list_item,null);
final LinearLayout layout = (LinearLayout)convertView.findViewById(R.id.mainLayout);
TextView t= (TextView)convertView.findViewById(R.id.textView1);
holder.textview = t;
holder.ll=layout;
final DrawView abc = (DrawView)convertView.findViewById(R.id.drawview);
holder.drawview=abc;
Log.e("Ronak","reached here3");
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textview.setText(mData.get(position));
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(c, "Clicked on="+position, 2).show();
ViewHolder mH = (ViewHolder) v.getTag();
LinearLayout.LayoutParams pp = new LinearLayout.LayoutParams(500,400);
mH.ll.setLayoutParams(pp);
DrawView dd=mH.drawview;
dd.x=position;
dd.invalidate();
}
});
return convertView;
}
static class ViewHolder {
public DrawView drawview;
public TextView textview;
public LinearLayout ll;
}
and my layout file for each row of ListView
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="2dp" >
<TextView
android:id="#+id/textView1"
android:layout_width="50dp"
android:layout_height="30dp"
android:text="Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<com.krish.horizontalscrollview.DrawView
android:id="#+id/drawview"
android:layout_width="150dp"
android:layout_height="100dp" >
</com.krish.horizontalscrollview.DrawView>
</LinearLayout>
My ListView class
public class CenterLockHorizontalScrollview extends HorizontalScrollView {
Context context;
int prevIndex = 0;
public CenterLockHorizontalScrollview(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
this.setSmoothScrollingEnabled(true);
}
public void setAdapter(Context context, CustomListAdapter mAdapter) {
try {
fillViewWithAdapter(mAdapter);
} catch (ZeroChildException e) {
e.printStackTrace();
}
}
private void fillViewWithAdapter(CustomListAdapter mAdapter)
throws ZeroChildException {
if (getChildCount() == 0) {
throw new ZeroChildException(
"CenterLockHorizontalScrollView must have one child");
}
if (getChildCount() == 0 || mAdapter == null)
return;
ViewGroup parent = (ViewGroup) getChildAt(0);
//parent.removeAllViews();
for (int i = 0; i < mAdapter.getCount(); i++) {
parent.addView(mAdapter.getView(i, null, parent));
}
}
I suppose you store a String list in mData. Make a class with members mData and mIsSelected (boolean) and pass an object of this class in the adapter. In onClick() check whether the row is already selected, invert the value of mIsSelected and perform the required operation at end call notifyDataSetChanged()
The first question that I have is that I have downloaded from the Internet MarkableImageView class to add a marker to an image I have already selected. The class is as follows:
public class MarkableImageView extends ImageView {
// Por defecto falso
private boolean checked = false;
public MarkableImageView(Context context) {
super(context);
}
public MarkableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MarkableImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setChecked(boolean checked) {
this.checked = checked;
invalidate();
}
public boolean isChecked() {
return checked;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(checked) {
Bitmap check = BitmapFactory.decodeResource(
getResources(), R.drawable.checkbox_on_background);
int width = check.getWidth();
int height = check.getHeight();
//int margin = 15;
int marginWidth = (int)(canvas.getWidth()/15);
int marginHeight = (int)(canvas.getHeight()/20);
int x = canvas.getWidth() - width - marginWidth;
//int y = canvas.getHeight() - height - margin;
int y = marginHeight;
canvas.drawBitmap(check, canvas.getWidth()-check.getWidth(), 1, new Paint());
}
}
}
I use a Gridview to show all my photos and I want to marked some. I use a BaseAdapter to load the data, here is my method getView ():
public View getView(int position, View convertView, ViewGroup parent) {
MarkableImageView imageView;
if(convertView == null) {
imageView = new MarkableImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams((int)(Preferencias.anchoPantalla/3.5), (int)(Preferencias.altoPantalla/4)));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
} else {
imageView = (MarkableImageView) convertView;
}
if(nivel == -1) {
if(!Preferencias.getIdsImagenesSeleccionadasJuegoMemoria().isEmpty()) {
if(Preferencias.getIdsImagenesSeleccionadasJuegoMemoria().size() > position) {
imageView.setImageResource(
Preferencias.imagenesTodas[Preferencias.getIdsImagenesSeleccionadasJuegoMemoria().get(position)]);
}
}
} else if(nivel == 0) {
if(!listaIdsDescubiertas.isEmpty()) {
if(listaIdsDescubiertas.size() > position) {
imageView.setImageResource(Preferencias.imagenesTodasPequeñas[listaIdsDescubiertas.get(position)]);
}
}
} else {
switch(nivel) {
case 1:
imageView.setImageResource(Preferencias.imagenesNivel1[position]);
break;
case 2:
imageView.setImageResource(Preferencias.imagenesNivel2[position]);
break;
}
if(!listaIdsDescubiertas.isEmpty()) {
for(Integer pos : listaIdsDescubiertas) {
if(calcularPosicion(position, nivel) == pos) {
imageView.setChecked(true);
}
}
}
}
return imageView;
}
Everything works perfectly but the problem is that when I start to move around the screen looks brand in the photos that I want to stop playing but the screen in certain positions marks are removed. Then touch the screen again reappears. How I can fix it to appear forever?
My second question is that I generate a grid where each image is a class called TileJuegoMemoria extending ImageView.
for (int r = 0; r < rows; r++) {
LinearLayout row = new LinearLayout(this);
row.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
row.setGravity(Gravity.CENTER);
for (int c = 0; c < columns; c++) {
TileJuegoMemoria tile = new TileJuegoMemoria(this, tilebackResource,
tilesImagenesRepetidas.get(position), position, sideLength, sideLength);
tile.setClickable(true);
tile.setId(position);
tile.setOnClickListener(tileOnClickListener);
row.addView(tile);
position++;
}
memoryBoardLayout.addView(row);
}
I add each object to a listener to click on it. The Listener has its method onClick () like this:
tileOnClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
TileJuegoMemoria tempTile = (TileJuegoMemoria) v;
if (tempTile.getVisibility() == TileJuegoMemoria.INVISIBLE || (!tempTile.isBackVisible)) {
return;
}
int move = gameEngine.doMove(tempTile);
if (move == -1) {
return;
}
gameEngine.selectedTile = tempTile;
gameEngine.selectedTile.flipOver();
if (move == 2) {
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
TileJuegoMemoria precedentMoveselectedTile = gameEngine.movesArray[0];
if (gameEngine.selectedTile.tileFace.equals(precedentMoveselectedTile.tileFace)) {
if(eliminarAcertados) {
gameEngine.selectedTile.hide();
precedentMoveselectedTile.hide();
}
} else {
gameEngine.selectedTile.flipOver();
precedentMoveselectedTile.flipOver();
turnoJugador1 = !turnoJugador1;
}
gameEngine.clearMoveArray();
}
});
}
}, 1000);
}
}
};
}
The game is for 2 players where they take turns playing two screen images that change. My question is how it might do so after Player 1's turn, was the computer who did click on two random images.
Where gender had thought the images saved in a list the coordinates of each image to PerformClick () on it. What I can do? Thanks!