I am trying to dial numbers from my app by clicking on different CardViews but its not working for me.
Everytime i tried adding an intent, the startActivity turns Red and pops out error message "cannot resolve method".
I even tried adding context before the startActivity() But it crashes the app.
I have 4 CardViews to be clicked in order to initiate a call and
I have 3 Java classes: CardViewDataAdapter where the recyclerView Holder was declared, MainActivity and itemObject
In activity_main i used recycler_view. In cardview_row i used card_view and bind it with recycler view.
Please kindly help me, i have googled this problem and also looked it up on stack overflow but no solution found yet.
The error message image
CardViewDataAdapter.java code:
public class CardViewDataAdapter extends RecyclerView.Adapter<CardViewDataAdapter.ViewHolder> {
private List<ItemObject> itemList;
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
// each data item is a string and an image in this case
public ImageView image_view;
public TextView image_name;
private Context context;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
this.image_view = (ImageView) itemLayoutView.findViewById(R.id.image_view);
this.image_name = (TextView) itemLayoutView.findViewById(R.id.image_name);
// Store the context
this.context = context;
// Attach a click listener to the entire row view
itemLayoutView.setOnClickListener(this);
}
// Handles the row being being clicked
#Override
public void onClick(View view) {
if (getPosition() == 0){
Intent callIntent = new Intent(Intent.ACTION_DIAL);
callIntent.setData(Uri.parse("tel:123456789"));
startActivity(callIntent);
} else if (getPosition() == 1){
Toast.makeText(view.getContext(), "position2 = " + getPosition(), Toast.LENGTH_SHORT).show();
} else if (getPosition() == 2){
Toast.makeText(view.getContext(), "position3 = " + getPosition(), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(view.getContext(), "position4 = " + getPosition(), Toast.LENGTH_SHORT).show();
}
//context.startActivity(intent);
}
}
// Create new views (invoked by the layout manager)
#Override
public CardViewDataAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(
R.layout.cardview_row, null);
// create ViewHolder
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
// - get data from your itemsData at this position
// - replace the contents of the view with that itemsData
viewHolder.image_view.setImageResource(itemList.get(position).getPhoto());
viewHolder.image_name.setText(itemList.get(position).getName());
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return this.itemList.size();
}
public CardViewDataAdapter(Context context, List<ItemObject> itemList) {
this.itemList = itemList;
}
}
MainActivity.java code:
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(true);
// use a GridLayout manager
mLayoutManager = new GridLayoutManager(this, 2);
mRecyclerView.setLayoutManager(mLayoutManager);
// specify an adapter
List<ItemObject> rowListItem = getAllItemList();
mAdapter = new CardViewDataAdapter(MainActivity.this, rowListItem);
mRecyclerView.setAdapter(mAdapter);
}
#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();
if (id == R.id.action_settings) {
Toast.makeText(getApplicationContext(), "Settings Clicked",
Toast.LENGTH_SHORT).show();
return true;
/* } else if (id == R.id.action_search) {
Toast.makeText(getApplicationContext(), "Search Clicked",
Toast.LENGTH_SHORT).show();
return true;*/
}
return super.onOptionsItemSelected(item);
}
//Handles the references to items displayed on each cards
private List<ItemObject> getAllItemList() {
List<ItemObject> allItems = new ArrayList<ItemObject>();
allItems.add(new ItemObject("Fire", R.drawable.fire));
allItems.add(new ItemObject("Ambulance", R.drawable.ambulance));
allItems.add(new ItemObject("Police", R.drawable.police));
allItems.add(new ItemObject("AntiSquad", R.drawable.police));
return allItems;
}
}
itemsObject.java code:
public class ItemObject {
private String name;
private int photo;
public ItemObject(String name, int photo) {
this.name = name;
this.photo = photo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPhoto() {
return photo;
}
public void setPhoto(int photo) {
this.photo = photo;
}
}
cardview_row.xml code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cardview="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<!-- CardView with customized attributes -->
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="170dp"
android:layout_gravity="center_horizontal"
android:layout_margin="10dp"
cardview:cardCornerRadius="20dp"
cardview:cardElevation="90dp"
android:elevation="2dp"
android:background="#drawable/myrect"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<ImageView
android:id="#+id/image_view"
android:layout_width="fill_parent"
android:layout_height="120dp"
/>
<TextView
android:id="#+id/image_name"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#4757b3"
android:textColor="#android:color/white"
android:fontFamily="sans-serif-condensed"
android:textSize="20sp"
android:textAlignment="center" />
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
Looks like you have a Context issue.
To get the context you need to alter your code to as below:
Intent callIntent = new Intent(Intent.ACTION_DIAL);
callIntent.setData(Uri.parse("tel:123456789"));
view.getContext().startActivity(callIntent);
Try this :
btnTelephone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Call 1st phone number api
Uri callIntentUri = Uri.parse("tel:"+telephoneStringForCall);
Intent callIntent = new Intent(Intent.ACTION_DIAL, callIntentUri);
startActivity(callIntent);
}
});
and check your views initialisation mb you lost something
Related
So I am trying to create an android app on alcohol and mixers, but have been stuck on the following problem for a while now...
I want to display every alcohol category (eg: Gin, Vodka, Whiskey, etc..) in a RecyclerView that scrolls horizontally, and every alcohol type (eg: Bourbon and Scotch for the Whiskey Category) in a RecyclerView that scrolls vertically.
I have created one adapter for each RecyclerView (CategoryAdapter for the horizontal RecyclerView called category, and MixerAdapter for the vertical RecyclerView called categoryDetails).
So far I've managed to create and display category as desired, but have some difficulties for categoryDetails.
Basically, I can't figure out how to update the contents of categoryDetails when an item of category is selected:
For example
If the user selects Whiskey in category, I want categoryDetails to display Bourbon and Scotch.
If the user then selects Gin, I want categoryDetails to only display Gin and Flavoured Gin, etc...
I hope I've been clear enough on what it is I want to accomplish!
Any help would be much appreciated, thanks!!
Here is a screenshot of how the screen appears when the activity is loaded.
If a user selects Rum (white on black RecyclerView), I want the RecyclerView currently showing Gin and Flavored Gin (black on white RecyclerView) to show the alcohols associated with the Rum category.
Screenshot
Here is the XML file holding the two recyclerViews category and categoryDetails
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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"
tools:context=".TipsDrinks">
<android.support.v7.widget.RecyclerView
android:id="#+id/category"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="#android:color/black"
android:orientation="horizontal"
android:scrollbars="horizontal"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/SpinnerPrompt" >
</android.support.v7.widget.RecyclerView>
<android.support.v7.widget.RecyclerView
android:id="#+id/categoryDetails"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:background="#android:color/white"
android:orientation="horizontal"
android:scrollbars="vertical"
android:visibility="visible"
app:layout_constraintBottom_toTopOf="#+id/adView4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/category"
app:layout_constraintVertical_bias="0.0">
</android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
The Class associated with the previous layout
public class TipsDrinks extends AppCompatActivity {
private CategoryAdapter categoryAdapter; // Adapter used for the category RecyclerView
public MixerAdapter mixerAdapter; //Adapter used for the categoryDetails RecyclerView
private RecyclerView categories; // The RecyclerView holding the name of each alcohol category
public RecyclerView catDetails; // The RecyclerView holding each type of that alcohol category
private DrinkMenu drinkMenu; // The DrinkMenu is another Class holding every Alcohol Category, the type of each alcohol and the mixers good with it
private ArrayList<String> drinkCat = new ArrayList<>(); // A String ArrayList holding the name of each alcohol category (Gin, Vodka, Rum, Whiskey, Other)
private ArrayList<Drink> drinkMixers = new ArrayList<>(); // A Drink(String, ArrayList<String>) ArrayList holding the mixers of every Drink
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tips_drinks);
categories = findViewById(R.id.category);
catDetails = findViewById(R.id.categoryDetails);
drinkMenu = new DrinkMenu();
setCategoryView(); // Creates the category RecyclerView
setDrinkMixers(); // Creates the categoryDetails RecyclerView
}
private void setCategoryView(){
categoryAdapter = new CategoryAdapter(drinkCat);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(TipsDrinks.this, LinearLayoutManager.HORIZONTAL, false);
categories.addItemDecoration(new DividerItemDecoration(TipsDrinks.this, DividerItemDecoration.HORIZONTAL));
categories.setLayoutManager(layoutManager);
categories.setItemAnimator(new DefaultItemAnimator());
categories.setAdapter(categoryAdapter);
prepareCategories();
}
private void prepareCategories(){
drinkCat.clear();
drinkCat.addAll(drinkMenu.getDrinkCategories());
for (String drink : drinkCat) {
System.out.println(drink);
}
categoryAdapter.notifyItemInserted(drinkCat.size() - 1);
}
private void setDrinkMixers() {
mixerAdapter = new MixerAdapter(drinkMixers);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
catDetails.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
catDetails.setLayoutManager(layoutManager);
catDetails.setItemAnimator(new DefaultItemAnimator());
catDetails.setAdapter(mixerAdapter);
prepareMixers();
}
private void prepareMixers() {
drinkMixers.clear();
drinkMixers.addAll(drinkMenu.getDrinkMixers(categoryAdapter.getCurrentCategory()));
mixerAdapter.notifyItemChanged(drinkMixers.size() -1);
}
}
The CategoryAdapter Class for the category RecyclerView
public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.MyViewHolder> {
private List<String> drinkList; //A List of String holding the category for each drink
private String textName = "Gin";
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TextView name; // The TextView holding the name of the category
MyViewHolder(View view) {
super(view);
view.setOnClickListener(this);
name = view.findViewById(R.id.catName);
}
#Override
public void onClick(View v) {
//Code to update the contents of the categoryDetails RecyclerView
}
}
CategoryAdapter(ArrayList<String> drinkList) { this.drinkList = drinkList; }
#Override
public CategoryAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.category_text, parent, false);
return new MyViewHolder(itemView);
}
#SuppressLint("SetTextI18n")
#Override
public void onBindViewHolder(CategoryAdapter.MyViewHolder holder, int position) {
String drink = drinkList.get(position);
holder.name.setText(drink);
textName = holder.name.getText().toString();
}
#Override
public int getItemCount() {
return drinkList.size();
}
public String getCurrentCategory() {
return textName;
}
}
The MixerAdapter Class for the categoryDetails RecyclerView
public class MixerAdapter extends RecyclerView.Adapter<MixerAdapter.MyViewHolder>{
private List<Drink> mixerList;
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView mixerCat, mixers;
MyViewHolder(View view) {
super(view);
view.setOnClickListener(this);
mixerCat = view.findViewById(R.id.mixerCat2);
mixers = view.findViewById(R.id.mixers2);
}
#Override
public void onClick(View v) {
if (mixers.getVisibility() == mixerCat.getVisibility()) {
mixers.setVisibility(View.GONE);
}
else {
mixers.setVisibility(View.VISIBLE);
}
}
}
MixerAdapter(ArrayList<Drink> mixerList) {
this.mixerList = mixerList;
}
#Override
public MixerAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.drinks_row, parent, false);
return new MixerAdapter.MyViewHolder(itemView);
}
#SuppressLint("SetTextI18n")
#Override
public void onBindViewHolder(MixerAdapter.MyViewHolder holder, int position) {
Drink drink = mixerList.get(position);
StringBuilder mixerStringList = new StringBuilder("");
holder.mixerCat.setText(drink.getSorM());
for (String mixer: drink.getMixers()) {
mixerStringList.append(mixer).append("\n");
}
holder.mixers.setText(mixerStringList.toString().trim());
}
#Override
public int getItemCount() {
return mixerList.size();
}
}
Create a callback interface in CategoryAdapter. When user clicks on an item in Category RecycleView, it's activity responsibility to populate MixerAdapter with new items as per selection.
CategoryAdapter
public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.MyViewHolder> {
private CategoryInterface callback;
CategoryAdapter(ArrayList<String> drinkList, CategoryInterface listener) {
this.drinkList = drinkList;
callback = listener;
}
#Override
public void onClick(View v) {
//Code to update the contents of the categoryDetails RecyclerView
callback.onItemSelected(getAdapterPosition());
}
public interface CategoryInterface {
void onItemSelected(int position);
}
}
Activity
public class TipsDrinks extends AppCompatActivity implements CategoryInterface {
private void setCategoryView(){
categoryAdapter = new CategoryAdapter(drinkCat, this);
}
#Override
void onItemSelected(int position) {
//Reassign items in MixerAdapter
}
}
that depends on your implementations , one global method which should work for all implementations is using HolderView method and using onTouchListener on the groups's root view
v.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP){
//the child should expand and be updated
}
return false;
}
});
So I am trying to make my cards clickable and as they are clicked it opens a new activity (not implemented in the code below though), here is my code:
For Interface
import android.view.View;
public interface ClickListener {
public void itemClicked(View view , int position);
}
For Adapter:
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.SensorViewHolder> {
private ClickListener clicklistener = null;
List<SensorData> sensors;
RVAdapter(List<SensorData> sensors) {
this.sensors = sensors;
}
public class SensorViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView sensorName;
TextView sensorDesc;
ImageView sensorPhoto;
private LinearLayout main;
SensorViewHolder(final View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cv);
sensorName = (TextView) itemView.findViewById(R.id.sensor_name);
sensorDesc = (TextView) itemView.findViewById(R.id.sensor_desc);
sensorPhoto = (ImageView) itemView.findViewById(R.id.sensor_photo);
main = (LinearLayout) itemView.findViewById(R.id.main);
main.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(itemView.getContext(), "Position:" + Integer.toString(getPosition()), Toast.LENGTH_SHORT).show();
if(clicklistener != null){
clicklistener.itemClicked(v, getAdapterPosition());
}
}
});
}
}
public void setClickListener(ClickListener clickListener){
this.clicklistener = clickListener;
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public SensorViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
SensorViewHolder pvh = new SensorViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(SensorViewHolder SensorViewHolder, int i) {
SensorViewHolder.sensorName.setText(sensors.get(i).name);
SensorViewHolder.sensorDesc.setText(sensors.get(i).descriptor);
SensorViewHolder.sensorPhoto.setImageResource(sensors.get(i).iconID);
}
#Override
public int getItemCount() {
return sensors.size();
}
}
and here is the code for MainActivity:
public class MainActivity extends AppCompatActivity {
private List<SensorData> sensorData;
private RecyclerView rv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Find the recycler view for the <code>
rv = (RecyclerView) findViewById(R.id.rv);
//Initialising a linear layout manager
final LinearLayoutManager llm = new LinearLayoutManager(this);
rv.setLayoutManager(llm);
rv.setHasFixedSize(true);
initializeData();
initializeAdapter();
rv.setClickListener(this);
}
private void initializeData() {
sensorData = new ArrayList<>();
sensorData.add(new SensorData("Accelerometer", "Measures the acceleration of a moving or vibrating body.", R.mipmap.ic_accl));
sensorData.add(new SensorData("GPS Sensor", "Provides real-time user location and time information.", R.mipmap.ic_gps));
sensorData.add(new SensorData("Proximity Sensor", "Provides ambient light and proximity sensing.", R.mipmap.ic_als));
}
private void initializeAdapter() {
RVAdapter adapter = new RVAdapter(sensorData);
rv.setAdapter(adapter);
}
}
And yet it seems I cannot access setClickListener. I must mention I am quite a beginner in this.
Where have I mistaken? Is this the correct way to implement clicks on a card or I am missing something?
Also here is the MainActivity XML if needed.
<?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:padding="16dp"
android:id="#+id/main">
<android.support.v7.widget.RecyclerView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#+id/rv">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
and items.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/cv"
app:cardUseCompatPadding="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/sensor_photo"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginRight="16dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/sensor_name"
android:layout_toRightOf="#+id/sensor_photo"
android:layout_alignParentTop="true"
android:textSize="30sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/sensor_desc"
android:layout_toRightOf="#+id/sensor_photo"
android:layout_below="#+id/sensor_name" />
</RelativeLayout>
</android.support.v7.widget.CardView>
EDIT: Just to avoid confusion, **I want the use to be able to click the cards and go to a new activity. ** How can I implement that in the simplest possible way? I am really confused on how to do it in the RecyclerView.
Thanks a lot and regards.
Since there is a difference between the old ListView and the new RecyclerView component, I have a reusable piece of code that I use to handle click events (both regular clicks and LongClicks):
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
#SuppressWarnings("CanBeFinal")
private GestureDetector mGestureDetector;
#SuppressWarnings("CanBeFinal")
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(View view, int position);
void onItemLongClick(View view, int position);
}
public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener)
{
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener()
{
#Override
public boolean onSingleTapUp(MotionEvent e)
{
return true;
}
#Override
public void onLongPress(MotionEvent e)
{
View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
if(childView != null && mListener != null)
{
mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView));
}
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e)
{
View childView = view.findChildViewUnder(e.getX(), e.getY());
if(childView != null && mListener != null && mGestureDetector.onTouchEvent(e))
{
mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent){}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
Then simply do this in your activity or fragment where you want to handle click events:
mRecyclerView.addOnItemTouchListener(new RecyclerItemClickListener(this, mRecyclerView, new RecyclerItemClickListener
.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
//start new activity here
}
#Override
public void onItemLongClick(View view, int position) {
}
}));
That should be the easiest way to do it!
I hope this helps you! Good luck and happy coding!
Basically you need to set the listener in the Viewholder
public class SensorViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView sensorName;
TextView sensorDesc;
ImageView sensorPhoto;
private LinearLayout main;
SensorViewHolder(final View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cv);
//Add the following line below
cv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//The intent firing goes here
}
});
sensorName = (TextView) itemView.findViewById(R.id.sensor_name);
sensorDesc = (TextView) itemView.findViewById(R.id.sensor_desc);
sensorPhoto = (ImageView) itemView.findViewById(R.id.sensor_photo);
main = (LinearLayout) itemView.findViewById(R.id.main);
main.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(itemView.getContext(), "Position:" + Integer.toString(getPosition()), Toast.LENGTH_SHORT).show();
if(clicklistener != null){
clicklistener.itemClicked(v, getAdapterPosition());
}
}
});
}
}
Hope it helps.
To fix the compiler error, the correct way to set a OnClickListener is with
rv.setOnClickListener()
Note that the error is because you are missing the word On. Generally, you should use autocomplete in Android Studio to help avoid these types of issues. If autocomplete doesn't pop up automatically, you can push Ctrl-Space to get it.
As a side note, you can build your project by clicking Build -> Make Project in the main menu. This will give a window with the error messages where you can copy and paste more easily than the usual error balloons.
first of all set tag for your card in onBindViewHolder:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.cv.setTag(position);
}
then add on click listener for your card in your view holder in adapter:
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public CardLayout cv;
public ViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(Rid.cv);
cv.setOnClickListener(this);
}
#Override
public void onClick(View v) {
//for find item that hold in list
int postition = (Integer) v.getTag();
...
}
In your findViewById you are casting the view to a RecyclerView and therefore you are referring the standard RecyclerView implementation of the Android framework. So this would never work.
The next thing is you are trying to set a listener to the RecyclerView but define the setListener method inside your adapter.
So what you should do is to either get a reference to your adapter via:
((RvAdapter) rv.getAdapter()).setClickListener();
after setting it or even better set the listener before you call
rv.setAdapter()
via
RvAdapter adapter = new RvAdapter();
adapter.setClickListener(listener)
I'm having an issue trying to build a layout where I have a CollapsingToolbar and a Scrollview
The ScrollView contains two CardViews and a RecyclerView
The CollapsingToolbar consists of an image, a title and no buttons for the moment
Activity Layout
Content Layout (The ScrollView is missing android:fillViewport="true")
With these layouts everything is alright except for the scrolling of course (the parallax doesn't work if I scroll on the cardviews which is annoying)
Here's the Adapter
public class HorariosAdapter extends RecyclerView.Adapter<HorariosAdapter.HorarioViewHolder> {
public static class HorarioViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView horaDesde;
HorarioViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cvHorario);
horaDesde = (TextView) itemView.findViewById(R.id.txtHora);
}
}
List<Horario> horarios;
HorariosAdapter(List<Horario> pHorarios){
this.horarios = pHorarios;
}
#Override
public int getItemCount() {
return horarios.size();
}
#Override
public HorarioViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.rvhorarios, viewGroup, false);
HorarioViewHolder hvh = new HorarioViewHolder(v);
return hvh;
}
#Override
public void onBindViewHolder(HorarioViewHolder horarioViewHolder, int i) {
horarioViewHolder.horaDesde.setText(horarios.get(i).getHoraDesde());
}
}
Over here we have the Activity
public class DetalleActivity extends AppCompatActivity {
final String EXTRA_ITEM = "Complejo";
private TextView txtDireccion;
private ImageView imgThumbnail;
private RecyclerView rvHorarios;
private HorariosAdapter adapter;
public DetalleActivity CustomListView = null;
private Cancha complejoSeleccionado;
private Horario horario;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
complejoSeleccionado = getIntent().getParcelableExtra(EXTRA_ITEM);
setContentView(R.layout.activity_detalle);
setToolbar(complejoSeleccionado.getComplejo().toString());
txtDireccion = (TextView) findViewById(R.id.txtDireccion);
imgThumbnail = (ImageView) findViewById(R.id.imgThumbnail);
txtDireccion.setText(complejoSeleccionado.getDireccion());
String lowerImagen = complejoSeleccionado.getImagen().toLowerCase();
int idImagen = getResources().getIdentifier(lowerImagen, "drawable", getPackageName());
imgThumbnail.setImageResource(idImagen);
rvHorarios = (RecyclerView) findViewById(R.id.rvHorarios);
rvHorarios.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(getApplicationContext());
rvHorarios.setLayoutManager(llm);
CustomListView = this;
horario = new Horario();
horario.initializeData();
adapter = new HorariosAdapter(horario.horarios);
rvHorarios.setAdapter(adapter);
rvHorarios.setNestedScrollingEnabled(false);
}
#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_detalle, 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
switch (id) {
case R.id.action_settings:
return true;
case R.id.action_search:
return true;
}
return super.onOptionsItemSelected(item);
}
private void setToolbar(String titulo)
{
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (complejoSeleccionado.getComplejo().toString() != null) {toolbar.setTitle(titulo);}
toolbar.inflateMenu(R.menu.menu_main);
toolbar.setNavigationIcon(R.drawable.ic_action_arrow);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent a = new Intent(getApplicationContext(), MainActivity.class);
a.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(a);
}
});
}
}
I've read about NestedScrollView but I don't think it would solve my problem
I also tried TouchHandlers but to no use
Question
How can I put all these three together and scroll them together?
EDIT 1: I know I shouldn't be using a RecyclerView inside a ScrollView, a possible solution could be to separate them in different tabs?
what you are looking for is parallax effect. This library will give you good idea about how to achieve that
I am working on ViewPager Concept. In ViewPager item cell contains two items such as ImageView and TextView.
Initially, i will download Blur Image and show in ViewPager cell. After this was completed, i will download HighResolution Image and show in ViewPager cell respectively.
For example, if i am looking at the first Item in ViewPager as Blur Image and in background it is downloading HighResolution image and then it must refresh the ViewPager and show the HighResolution Image in the respectively view cell.
After swiping two items and then back to the first Item, that time it shows the High Resolution Image.
So my issue is without swiping left or right, i need to refresh the current view if any changes happened in the current view.
ViewPager Activity Class:
public class ViewPagerActivity extends Activity {
ViewPager pager;
String[] _blurImageURL;
PagerAdapter _pagerAdapter;
Context _context;
ViewPagerModel vpModel = new ViewPagerModel();
ArrayList<String> lstQueue=new ArrayList<String>();
Handler _handler=new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_pager);
pager = (ViewPager) findViewById(R.id.pagerView);
_context = this;
_blurImageURL = new String[]{
"http://cdn.connollyphoto.nyc/wp-content/uploads/2014/06/cp_seanbell_portrait_002-800x1200.jpg",
"http://static.wixstatic.com/media/e6f301_7d57a9c0ebdf4d438f88633637aaed77.jpg_srz_930_1395_85_22_0.50_1.20_0.00_jpg_srz",
"http://a4.format-assets.com/image/private/s--TmkImGBO--/c_limit,g_center,h_1200,w_65535/a_auto,fl_keep_iptc.progressive,q_95/31336-7293530-portrait-1_jpg2.jpg",
"http://daviddodgephotography.com/wp-content/uploads/2015/03/Donna_12.jpg",
"http://a3.format-assets.com/image/private/s--W9Flct-g--/c_limit,g_center,h_1200,w_65535/a_auto,fl_keep_iptc.progressive,q_95/173355-8951465-Marvin_Portraits-005.jpg",
"http://www.leifnorman.net/wp-content/uploads/2014/10/IMG_6070.jpg",
"https://dwaynefoong.files.wordpress.com/2012/05/amin-fashion-portrait-dwayne-foong-photography.jpg",
"https://m1.behance.net/rendition/modules/117495331/hd/ce856c4a1fb4c09a5ecec05839f6ddc4.jpg",
"http://www.pcimagenetwork.com/perks/Perks%202013.jpg",
};
_pagerAdapter = new ViewPagerAdapter(_context, vpModel, this);
pager.setAdapter(_pagerAdapter);
// Calling Volley Library to Download the Image for each URLi
for (int i = 0; i < _blurImageURL.length; i++) {
String fileName = String.valueOf(i);
fileName=fileName+"_blurImg";
DownloadImages(_blurImageURL[i], fileName, true);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.view_pager, 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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void updateView() {
_pagerAdapter.notifyDataSetChanged();
}
public void DownloadQueue(String url_in,String fileName_in)
{
if(lstQueue.contains(fileName_in))
{
Log.i("Duplicate_Request=",fileName_in);
}
else{
lstQueue.add(fileName_in);
DownloadImages(url_in,fileName_in,false);
}
}
void DownloadImages(String imageURL_in, final String fileName_in, final boolean isBlur_in) {
ImageRequest imageRequest = new ImageRequest(imageURL_in,
new Response.Listener<Bitmap>() {
#Override
public void onResponse(final Bitmap response) {
try {
Log.v("Response_Received =",fileName_in);
// Saved in SD Card and getting the Path
String imagePath = SavedInSDCard(response,fileName_in);
//updating the Model
if (isBlur_in) {
vpModel.blurImgLocalPath.add(imagePath);
} else {
vpModel.highResolutionImgLocalPath.add(imagePath);
}
//updating the View
_handler.post(new Runnable() {
#Override
public void run () {
updateView();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}, 0, 0, null, null);
ApplicationController.getInstance().addToRequestQueue(imageRequest);
}
public String SavedInSDCard(Bitmap bitmap, String fileName_in) {
File dir = new File(ApplicationController.getAppContext()
.getExternalFilesDir("ViewPager_POC") + "/Cache");
// Create the storage directory if it does not exist
if (!dir.exists()) {
dir.mkdirs();
}
File file = new File(dir, fileName_in);
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
String imgPath = dir + "/" + fileName_in;
return imgPath;
}
}
ViewPager Adapter Class:
public class ViewPagerAdapter extends PagerAdapter {
Context _context;
LayoutInflater inflater;
ViewPagerActivity _vpActivity;
String[] _highResolutionURL = new String[]{
"http://www.monportraitpro.fr/wp-content/uploads/2014/08/Philippe-Vasilescu.jpg",
"http://www.markhicksphotography.com/wp-content/uploads/2012/01/MHP2012_01_04_MHP_DSC0003.jpg",
"http://www.andrew-mason.com/wp-content/uploads/2013/05/portrait-1-3.jpg",
"http://shutterfinger.typepad.com/.a/6a00e551a6244a8833019affd0eb14970d-pi",
"http://www.antonioolmos.com/data/photos/90_1childs_livebooks.jpg",
"http://www.dvdsreleasedates.com/pictures/800/12000/Zachary-Quinto.jpg",
"http://www.glnphotography.com/wp-content/uploads/2013/09/IMG_1347.jpg",
"http://www.dvdsreleasedates.com/pictures/800/12000/Paul-Walker.jpg",
"http://www.antonioolmos.com/data/photos/89_1blairbooks.jpg",
};
ArrayList<String> _blurImgPath;
ArrayList<String> _highResolutionImgPath;
public ViewPagerAdapter(Context context_in, ViewPagerModel vpModel_in, ViewPagerActivity activity_in) {
_context = context_in;
_blurImgPath = vpModel_in.blurImgLocalPath;
_highResolutionImgPath = vpModel_in.highResolutionImgLocalPath;
_vpActivity = activity_in;
}
#Override
public int getCount() {
return _blurImgPath.size();
}
#Override
public void destroyItem(View container, int position, Object object) {
// TODO Auto-generated method stub
((ViewPager) container).removeView((View) object);
}
#Override
public Object instantiateItem(ViewGroup container, final int position) {
// Declare Variables
TextView txtCounter;
final ImageView imgView;
inflater = (LayoutInflater) _context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.view_pager_item, container,
false);
txtCounter = (TextView) itemView.findViewById(R.id.counter);
imgView = (ImageView) itemView.findViewById(R.id.images);
//Setting the values for Image and textview
txtCounter.setText("" + (position + 1));
//Setting the Image
if (position < _highResolutionImgPath.size()) {
//Setting Hi-ResImage
Log.v("HighRes_ImgPath=", "Get Image from Model" );
imgView.setImageBitmap(BitmapFactory.decodeFile(_highResolutionImgPath.get(position)));
} else {
// Generating the request for HighResolution Image
String fileName = String.valueOf(position + 10);
fileName = fileName + "_clearImg";
Log.v("HighRes_ImgPath=", "Sending Request to Queue=" + fileName);
_vpActivity.DownloadQueue(_highResolutionURL[position], fileName);
//Setting the BlurImage
imgView.setImageBitmap(BitmapFactory.decodeFile(_blurImgPath.get(position)));
}
// Add viewpager_item.xml to ViewPager
((ViewPager) container).addView(itemView);
return itemView;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((RelativeLayout) object);
}
}
ViewPager Model:
public class ViewPagerModel {
ArrayList<String> blurImgLocalPath=new ArrayList<String>();
ArrayList<String> highResolutionImgLocalPath=new ArrayList<String>();
}
activity_view_pager.xml
<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="com.example.poc_viewpager.ViewPagerActivity" >
<android.support.v4.view.ViewPager
android:id="#+id/pagerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
/>
view_pager_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="match_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/images"
android:layout_width="match_parent"
android:layout_height="400dp"
android:layout_alignParentLeft="true" />
<TextView
android:id="#+id/counter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="43dp" />
</RelativeLayout>
In this case, I would use Picasso :
For example :
Picasso.with(getActivity())
.load(URL_THUMBNAIL) // thumbnail url goes here
.into(IMAGEVIEW, new Callback() { // Your image view
// On success start loading the full resolution image
#Override
public void onSuccess() {
Picasso.with(getActivity())
.load(FULL_RESOLUTION_URL) // image url goes here
.into(IMAGEVIEW);
}
#Override
public void onError() {
// Manage downloading errors here
}
});
The updateView()is called on the background thread. notifyDataSetChanged() does not work on the background thread. Call the notifyDataSetChanged() method on the UI thread and it should solve your problem
I have a list view in left of the screen and on click of the item i want to update a text on the right half of the screen, what i want to do here is that to move the clicked item in center of the listview. Like if the item is on top and i click on it it automatically moves to the center of the list view, how I can do this? Any kind of help will be appreciated.
I have a listview in which 7 items are visible and on startup 4th item will be selected as this is in center of the visible items in listview and if there are n items and whichever item is selected by user will be in center of the visible items in listview. Like i have 10 items and on start 4th is selected and when user selects the 3rd item, nth item from listview should come to index zero and and 3rd will come to position 4. Similarly for every other selected item? Can any one provide a code snippet for this?
Change items order in ListView source Array and then call notifyDataSetChanged() in ListView Adapter
EDIT: Code sample
public class ListAdapter extends BaseAdapter{
private Activity activity;
private ArrayList<ListRowObject> listItems;
public ListAdapter(Activity activity){
this.activity = activity;
listItems = new ArrayList<ListRowObject>();
}
public void addItem(ListRowObject item){
listItems.add(item);
notifyDataSetChanged();
}
public void addItems(ArrayList<ListRowObject> items){
listItems = items;
notifyDataSetChanged();
}
public void clear(){
listItems = null;
listItems = new ArrayList<ListRowObject>();
notifyDataSetChanged();
}
#Override
public int getCount() {
return listItems.size();
}
#Override
public Object getItem(int position) {
return listItems.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
ViewHolder holder;
if(convertView == null){
holder = new ViewHolder();
convertView = activity.getLayoutInflater().inflate(R.layout.list_row, null);
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.bgLayout = (LinearLayout) convertView.findViewById(R.id.bgLayout);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
ListRowObject row = listItems.get(position);
if(row.isSelected())
holder.bgLayout.setBackgroundColor(Color.GRAY);
else
holder.bgLayout.setBackgroundColor(Color.WHITE);
holder.text.setText(row.getText());
return convertView;
}
}
//--------
public class ListRowObject {
private String text;
private int positionInList;
private boolean isSelected;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public int getPositionInList() {
return positionInList;
}
public void setPositionInList(int positionInList) {
this.positionInList = positionInList;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean selected) {
isSelected = selected;
}
}
//------
public class Main extends Activity {
private ListView listView;
private ListAdapter adapter;
private Activity activity;
private ArrayList<ListRowObject> items;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
activity = this;
initializeFormViews();
initializeOnClickEvents();
fillList();
}
private void initializeFormViews(){
listView = (ListView) findViewById(R.id.listView);
}
private void initializeOnClickEvents(){
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Toast.makeText(activity, "Pressed " +position, Toast.LENGTH_SHORT).show();
// unselect all rows
for(ListRowObject item : items){
item.setSelected(false);
}
int first = adapterView.getFirstVisiblePosition();
int last = adapterView.getLastVisiblePosition();
int centerPosition = (first + last) / 2;
// change bg for centerPosition row
adapterView.getChildAt(centerPosition).findViewById(R.id.bgLayout).setBackgroundColor(Color.GRAY);
changeItems(position, centerPosition);
}
});
}
private void changeItems(int pressedPosition, int centerPosition){
ListRowObject centerRow = items.get(centerPosition);
ListRowObject pressedRow = items.get(pressedPosition);
pressedRow.setSelected(true);
centerRow.setSelected(false);
items.remove(centerPosition);
items.add(centerPosition, pressedRow);
items.remove(pressedPosition);
items.add(pressedPosition, centerRow);
adapter.clear();
adapter.addItems(items);
}
private void fillList(){
adapter = new ListAdapter(activity);
items = new ArrayList<ListRowObject>();
items = getItems();
for(ListRowObject item : items){
adapter.addItem(item);
}
listView.setAdapter(adapter);
}
private ArrayList<ListRowObject> getItems(){
ArrayList<ListRowObject> result = new ArrayList<ListRowObject>();
for(int i = 0; i < 15; i++){
ListRowObject object = new ListRowObject();
object.setPositionInList(i);
object.setText("Item #" + i);
if(i != 4)
object.setSelected(false);
else
object.setSelected(true);
result.add(object);
}
return result;
}
}
//------
public class ViewHolder {
public TextView text;
public LinearLayout bgLayout;
}
list_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="50dp"
android:id="#+id/bgLayout">
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:id="#+id/text"
android:textColor="#000000"
android:textSize="24dp"
android:gravity="center"/>
</LinearLayout>
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/listView"/>
</LinearLayout>
when you create ArrayAdapter for your listview you send a ListArray to it.when you want change content .you only change this listArray then when click your item you can change ListArray and call notifyDataSetChanged(); method your adapter.