1

It uses retrofit 2.0 to fetch the data from the webservice and bind it to the card view. When I click on the card view having image and textviews, on click is not triggering, rather a strange behaviour is at the very corner edges of the card view onclick is triggering.

Item_row.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp"
    card_view:cardCornerRadius="1dp">

    <RelativeLayout

        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="8dp"
        android:layout_margin="5dp"
        android:clickable="true">

        <ImageView
            android:id="@+id/flowerImage"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:focusable="true"
            android:clickable="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_alignParentTop="true"
            android:visibility="visible"/>
        <ImageButton
            android:id="@+id/favIcon"
            android:layout_width="32dp"
            android:layout_height="32dp"
            android:scaleType="fitXY"
            android:layout_margin="5dp"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:descendantFocusability="blocksDescendants"
            android:background="@drawable/ic_favorite_border"
            android:focusable="true"
            android:clickable="true"
            />



        <LinearLayout

            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/flowerImage"

            android:orientation="vertical"
            >

            <TextView
                android:id="@+id/flowerName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Medium Text"
                android:textColor="@color/colorPrimary"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:focusable="true"
                android:clickable="true"
                android:visibility="visible"/>

            <TextView
                android:id="@+id/flowerCategory"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Small Text"
                android:layout_alignBottom="@id/flowerName"
                android:textAppearance="?android:attr/textAppearanceSmall"
                android:focusable="true"
                android:clickable="true"
                android:visibility="visible"/>

            <TextView
                android:id="@+id/flowerPrice"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignBottom="@id/flowerCategory"
                android:text="New Text"
                android:focusable="true"
                android:clickable="true"
                android:visibility="visible"/>

            <TextView
                android:id="@+id/flowerInstruction"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:visibility="gone"
                android:text="New Text"
                android:focusable="true"
                android:clickable="true"/>

        </LinearLayout>


    </RelativeLayout>


</android.support.v7.widget.CardView>

Content_main.xml Layout file

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:layout_margin="8dp"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/swipe"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/list"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:scrollbars="vertical"/>


        </android.support.v4.widget.SwipeRefreshLayout>


</RelativeLayout>



</LinearLayout>

Main Activity Layout file activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"
            android:elevation="8dp"/>

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>

The code base is following MVC design pattern. Controller does the job of getting the web service data

MainActivity.java

package com.innovation.myapp.jwelleryonrent.View;

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Toast;

import com.innovation.myapp.jwelleryonrent.R;
import com.innovation.myapp.jwelleryonrent.controller.jwelleryController;
import com.innovation.myapp.jwelleryonrent.model.adapter.CustomItemClickListner;
import com.innovation.myapp.jwelleryonrent.model.adapter.JwelleryAdapter;
import com.innovation.myapp.jwelleryonrent.model.pojo.JwelleryCollection;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements jwelleryController.JwelleryCallbackListener {
    private Toolbar mToolbar;
    private RecyclerView mRecyclerView;
    private SwipeRefreshLayout mSwipeRefreshLayout;
    private List<JwelleryCollection> mJwelleryList = new ArrayList<>();
    private JwelleryAdapter mJwelleryAdapter;
    private jwelleryController mController;
    private boolean isInFavourites = false;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        configToolbar();
        mController = new jwelleryController(MainActivity.this);
        configViews();



        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });




    }


    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState)
    {
        View rootView = inflater.inflate(R.layout.item_row, container, false);
        ImageButton imgBtn = (ImageButton) findViewById(R.id.favIcon);
        imgBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addItemToBag(v);
            }
        });
        return rootView;
    }


    private void addItemToBag(View v)
    {
        isInFavourites = true;
        ImageButton btnFaviourite = (ImageButton) findViewById(R.id.favIcon);
        if(isInFavourites==true) {

            btnFaviourite.setImageResource(R.drawable.ic_favorite_white_24dp);
        }
        else
            btnFaviourite.setImageResource(R.drawable.ic_favorite_border);
        Snackbar.make(v, "Item added to Favourites", Snackbar.LENGTH_LONG)
                .setAction("Action", null).show();
    }


    private void configToolbar() {
        mToolbar = (Toolbar) this.findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);
    }

    private void initializeAdapter()
    {
        mJwelleryAdapter = new JwelleryAdapter(mJwelleryList, new CustomItemClickListner() {
            @Override
            public void onItemClick(View v, int position) {
                Toast.makeText(MainActivity.this, "Clicked Item: "+position,Toast.LENGTH_LONG).show();
            }
        });
        mRecyclerView.setAdapter(mJwelleryAdapter);

        mSwipeRefreshLayout.setColorSchemeColors(getResources().getColor(R.color.colorAccent),
                getResources().getColor(R.color.colorPrimary),
                getResources().getColor(R.color.colorPrimaryDark));

        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                mController.startFetching();
            }
        });


    }


    private void configViews() {
        mRecyclerView = (RecyclerView) this.findViewById(R.id.list);
        mSwipeRefreshLayout = (SwipeRefreshLayout) this.findViewById(R.id.swipe);

        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
        mRecyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());
        mController.startFetching();
        initializeAdapter();
//        mJwelleryAdapter= new JwelleryAdapter(mJwelleryList);

    }

        @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

        @Override
        public void onFetchStart() {

        }

        @Override
        public void onFetchProgress(JwelleryCollection jwellery) {
            mJwelleryAdapter.addJwellery(jwellery);
        }

        @Override
        public void onFetchProgress(List<JwelleryCollection> jwelleryList) {

        }

        @Override
        public void onFetchComplete() {
            mSwipeRefreshLayout.setRefreshing(false);
        }

        @Override
        public void onFetchFailure() {

        }
}

Recycler view uses the adapter view holder pattern to initialize the adapter JwelleryAdapter class

package com.innovation.myapp.jwelleryonrent.model.adapter;

import android.content.Context;
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;
import android.widget.Toast;

import com.innovation.myapp.jwelleryonrent.R;
import com.innovation.myapp.jwelleryonrent.View.MainActivity;
import com.innovation.myapp.jwelleryonrent.model.pojo.JwelleryCollection;
import com.innovation.myapp.jwelleryonrent.model.utilities.Constants;
import com.squareup.picasso.Picasso;

import java.util.List;

/**
 * 
 */
public class JwelleryAdapter extends RecyclerView.Adapter<JwelleryAdapter.Holder> {
    private List<JwelleryCollection> mJwelleryCollection;
    CustomItemClickListner  itemListner;
    Context mContext;

    public JwelleryAdapter(List<JwelleryCollection> jwellery) {
        mJwelleryCollection = jwellery;

    }
    public JwelleryAdapter(  List<JwelleryCollection> jwellery,CustomItemClickListner listner) {
        mJwelleryCollection = jwellery;
        this.itemListner = listner;

    }

    @Override
    public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
        View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row,parent,false);
        final Holder mViewHolder = new Holder(row);
        row.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                itemListner.onItemClick(v,mViewHolder.getPosition());
            }
        });
        return mViewHolder;
    }



    @Override
    public void onBindViewHolder(JwelleryAdapter.Holder holder, int position) {
        JwelleryCollection currentJwellery = mJwelleryCollection.get(position);
        holder.mName.setText(currentJwellery.mName);
        holder.mCategory.setText(currentJwellery.mCategory);
        holder.mPrice.setText(Double.toString(currentJwellery.mPrice));
        holder.mInstructions.setText(currentJwellery.mInstructions);

        Picasso.with(holder.itemView.getContext()).load(Constants.PHOTO_URL + currentJwellery.mPhoto).into(holder.mImage);


    }
    public void addJwellery(JwelleryCollection jwellery) {
        mJwelleryCollection.add(jwellery);
        notifyDataSetChanged();
    }
    @Override
    public int getItemCount() {
        return mJwelleryCollection.size();
    }
    public class Holder extends RecyclerView.ViewHolder implements View.OnClickListener {
        Context contxt;
        public TextView mName, mCategory, mPrice, mInstructions;
        public ImageView mImage;

        public Holder(View itemView) {
            super(itemView);
            mImage = (ImageView) itemView.findViewById(R.id.flowerImage);
            mName = (TextView) itemView.findViewById(R.id.flowerName);
            mCategory = (TextView) itemView.findViewById(R.id.flowerCategory);
            mPrice = (TextView) itemView.findViewById(R.id.flowerPrice);
            mInstructions = (TextView) itemView.findViewById(R.id.flowerInstruction);




        }


        public Holder(View itemView,int ViewType,Context c) {
        // Creating ViewHolder Constructor with View and viewType As a parameter
            super(itemView);
            contxt = c;
            itemView.setClickable(true);
            itemView.setOnClickListener(this);
        }
        @Override
        public void onClick(View v) {

        Toast.makeText(contxt, "The Item Clicked is: " + getPosition(), Toast.LENGTH_SHORT).show();
            }
        }


}

CustomerItemClickListner Interface to handle row item on click

package com.innovation.myapp.jwelleryonrent.model.adapter;

import android.view.View;

/**
 * 
 */
public interface CustomItemClickListner {
    public void onItemClick(View v,int position);
}
halfer
  • 19,824
  • 17
  • 99
  • 186
Vimal
  • 13
  • 5

1 Answers1

0

First create one variable of your interface in your adapter:

CustomItemClickListener mListener;

then like you have set in your OnClick() method:

if (mListener != null) {
    mListener.onItemClick(v, getAdapterPosition());
}

and the last thing you need to modify in your adapter is creating new method which you will call later in your activity class for handling listener:

public void setOnItemClickListener(CustomItemClickListener listener) {
     mListener = listener;
}

now you can call this method in your activity like this:

adapter.setOnItemClickListener(this); // implement interface

           // or

adapter.setOnItemClickListener(new CustomItemClickListener());
Dusan Dimitrijevic
  • 3,169
  • 6
  • 22
  • 46
  • variable for interface is already created in adapter and listener is already initialize in the adapter constructor if you see the code. Do you suggest to initialize it in setOnItemClickListener? – Vimal Mar 03 '16 at 20:00
  • From MainActivity, do I need to call adapter.setOnItemClickListener(this); where as if you see MainActivity.java it has already mJwelleryAdapter = new JwelleryAdapter(mJwelleryList, new CustomItemClickListner() { @Override public void onItemClick(View v, int position) { Toast.makeText(MainActivity.this, "Clicked Item: "+position,Toast.LENGTH_LONG).show(); } }); mRecyclerView.setAdapter(mJwelleryAdapter); in InitializeAdapter method – Vimal Mar 03 '16 at 20:02
  • Yes, and i'm sure that it will work if you are working on implementation of listener for one custom row view. Also when you are calling onItemClick method from interface, check if mListener isn't null first. Let me know if it's working. – Dusan Dimitrijevic Mar 03 '16 at 20:04
  • Remove your implementation of interface and do the same as i have done. – Dusan Dimitrijevic Mar 03 '16 at 20:05
  • Modification I did in InitializeAdapter in MainActivity.Java mJwelleryAdapter.setOnItemClickListner(new CustomItemClickListner() { @Override public void onItemClick(View v, int position) { Toast.makeText(MainActivity.this, "Clicked Item: "+position,Toast.LENGTH_LONG).show(); } }); Created method in Adapter class public void setOnItemClickListner(CustomItemClickListner listner) { itemListner = listner; } – Vimal Mar 03 '16 at 20:09
  • Under CreateViewHolder made this change if(itemListner!=null) itemListner.onItemClick(v,mViewHolder.getPosition()); Still the same issue exists, if I tap on card anywhere toast is not showing, but If I tap on corner/edge of the card somewhere it shows toast – Vimal Mar 03 '16 at 20:11
  • Any more suggestions you can give after looking at the my code? please – Vimal Mar 03 '16 at 20:14
  • Is there a way I can share my whole project to you? – Vimal Mar 03 '16 at 20:14
  • We can continue discussion in chat – Dusan Dimitrijevic Mar 03 '16 at 20:15
  • About sharing your project, the best way would be to send me a text file with MainActivity code and one more text file with Adapter code – Dusan Dimitrijevic Mar 03 '16 at 20:16
  • I see you have put `android:clickable="true"` only on RelativeLayout view. Try putting it on the root of layour and that it's in CardView or just remove it. – Dusan Dimitrijevic Mar 03 '16 at 20:19
  • I tried putting android:clickable="true" on cardview and tried after removing as well but seems it is not working also, how can I attach the files? – Vimal Mar 03 '16 at 20:25
  • check this answer http://stackoverflow.com/questions/27081787/onclicklistener-for-cardview – Dusan Dimitrijevic Mar 03 '16 at 20:26
  • Finally I got it working, thanks Dusan Dimitrijevic for your quick help, because of you it is solved. I have 1 more issue though which I have posted on below link, can you please help with that http://stackoverflow.com/questions/35783827/onclick-event-is-not-triggered-for-image-button-placed-on-image-view-in-the-card – Vimal Mar 03 '16 at 21:57
  • No problem Vimal. I will investigate that issue. – Dusan Dimitrijevic Mar 03 '16 at 22:00