I'm making an app that requires the use of a Gallery. My problem is, the Gallery is really choppy. My code is pretty much similar to the sample code that android provides, but rather than just having the ImageAdapter return an ImageView, I have it return a LinearLayout, because I need text underneath the image. Any suggestions?
Here's my code:
package org.example.gallery;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class GalleryTestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Gallery gallery = (Gallery) this.findViewById(R.id.gallery);
gallery.setAdapter(new ItemAdapter(this));
gallery.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Toast.makeText(GalleryTestActivity.this, "" + position,
Toast.LENGTH_SHORT).show();
}
});
}
public class ItemAdapter extends BaseAdapter {
private Context mContext;
private final Integer[] mImageIds = { R.drawable.sample_1,
R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4,
R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7,
R.drawable.sample_8 };
private final String[] mStringIds = { "1-pc. Chicken with Rice",
"2-pc. Chicken with Rice", "Tower Burger", "Bucket", "Barrel",
"Chicken Fillet", "Chicken burger", "Another Chicken Burger" };
public ItemAdapter(Context c) {
this.mContext = c;
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout l = new LinearLayout(this.mContext);
l.setOrientation(LinearLayout.VERTICAL);
ImageView iv = new ImageView(this.mContext);
iv.setImageResource(mImageIds[position]);
iv.setScaleType(ImageView.ScaleType.FIT_CENTER);
TextView tv = new TextView(this.mContext);
tv.setText(mStringIds[position]);
tv.setTextSize(20);
tv.setTextColor(Color.RED);
tv.setGravity(Gravity.CENTER_HORIZONTAL);
l.addView(iv);
l.addView(tv);
return l;
}
}
}
use ViewHolder(so u will not inflating/creating view in every getView call(views are recycling)) pattern like in this example:
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/List14.html
EDIT:
static class ViewHolder {
TextView tv;
ImageView iv;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
LinearLayout l = new LinearLayout(this.mContext);
l.setOrientation(LinearLayout.VERTICAL);
ImageView iv = new ImageView(this.mContext);
iv.setScaleType(ImageView.ScaleType.FIT_CENTER);
TextView tv = new TextView(this.mContext);
tv.setTextSize(20);
tv.setTextColor(Color.RED);
tv.setGravity(Gravity.CENTER_HORIZONTAL);
l.addView(iv);
l.addView(tv);
convertView = l;
holder = new ViewHolder();
holder.tv = tv;
holder.iv = iv;
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.tv.setText(mStringIds[position]);
holder.iv.setImageResource(mImageIds[position]);
return convertView;
}
Related
Thank you in advance and dont be very hard with me, it is my first question.
I was trying to add a new item to my recyclerView through the adapter by declaring a method in my adapter called addItem(String newItem)
Then I tried to call this method when the floating button is clikced and the problem is that the method does not even appear when i hit cntrl+space and if i write it down it gets on red.
I have already tried to rebuild the project and nothing changes.
¿Any ideas about how to solve it?
MainActivity class
package com.example.sakur.recyclerviewapp;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private FloatingActionButton mFloatingActionButton;
private List<String> recyclerItems = Collections.emptyList();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
recyclerItems = new ArrayList<>();
recyclerItems.add("First item");
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new MyAdapter(recyclerItems);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.floating_action_button);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String itemNuevo = "New Card";
mAdapter.addItem(itemNuevo);
Snackbar.make(view, "Item added successfully", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
#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);
}
}
and the MyAdapter class
package com.example.sakur.recyclerviewapp;
import android.content.Context;
import android.graphics.drawable.Drawable;
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 java.util.Collections;
import java.util.List;
/**
* Created by Sakur on 19/12/2015.
*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<String> mDataset= Collections.emptyList();
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<String> myDataset) {
mDataset = myDataset;
}
public void addItem(String newItem){
mDataset.add(newItem);
notifyDataSetChanged();
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_card, parent, false);
// set the view's size, margins, paddings and layout parameters
//...
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.mTextView.setText(mDataset.get(position));
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView mTextView;
public ImageView mImageView;
public ViewHolder(View v) {
super(v);
mTextView = (TextView) v.findViewById(R.id.text_card);
}
}
}
addItem(String) is not a method of RecyclerView.Adapter, but of your MyAdapter subclass. Obviously, RecyclerView.Adapter has no knowledge of the existence neither of your MyAdapter nor of your addItem(String).
you can either change
private RecyclerView.Adapter mAdapter;
into
private MyAdapter mAdapter;
or cast mAdapter. E.g.
if (mAdater instanceof MyAdapter) {
((MyAdapter) mAdapter).addItem(...);
}
I would like to implement a new intent when my card from CardView is clicked. I have already implemented for one of the cards. Is there any other way in which the adapter is able to identify the position and bring to a new activity for each card? Like linking the each card to their individual activity with a template layout. (The new activity for each card will be of the same layout, just different texts and images).
I have added an ImageButton on my cards. However, when I click on the ImageButton, it does not bring me to the new activity. Clicking on the card edges/portion and not the image itself would work. Is there something I missed out on my code? I can't seem to get it.
Here are my codes:
MuaActivity.java
package android.com.example.weddingappfinale;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.inputmethod.EditorInfo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import Adapters.MuaAdapter;
import CustomerActivities.ShimaMatinActivity;
public class MuaActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private MuaAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mua_list);
getSupportActionBar().setTitle("Make Up Artists");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
final ArrayList<MuaView> muaView = new ArrayList<>();
muaView.add(new MuaView(R.drawable.mua_image, "Shima Matin Bridal Services"));
muaView.add(new MuaView(R.drawable.mua_image, "Aake Up Artist Pte Ltd"));
muaView.add(new MuaView(R.drawable.mua_image, "Lake Up Artist 3Pte Ltd"));
muaView.add(new MuaView(R.drawable.mua_image, "f Up Artist Pte Ltd"));
// ArrayList
mRecyclerView = findViewById(R.id.recycler_view_list);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mAdapter = new MuaAdapter(muaView);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(new MuaAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position) {
Intent i = new Intent (MuaActivity.this, ShimaMatinActivity.class);
startActivity(i);
finish();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.search, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
mAdapter.getFilter().filter(newText);
return false;
}
});
return true;
}
}
MuaAdapter.java
package Adapters;
import android.com.example.weddingappfinale.MuaView;
import android.com.example.weddingappfinale.R;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class MuaAdapter extends RecyclerView.Adapter<MuaAdapter.MuaViewHolder> implements Filterable {
private ArrayList<MuaView> mMuaView;
private ArrayList<MuaView> mMuaViewFull;
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public static class MuaViewHolder extends RecyclerView.ViewHolder {
public ImageButton mImageButton;
public TextView mTextView1;
public MuaViewHolder(#NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
mImageButton = itemView.findViewById(R.id.mua_imageButton);
mTextView1 = itemView.findViewById(R.id.mua_title);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onItemClick(position);
}
}
}
});
}
}
public MuaAdapter(ArrayList<MuaView> muaView) {
this.mMuaView = muaView;
mMuaViewFull = new ArrayList<>(muaView);
}
#NonNull
#Override
public MuaViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.mua_view, parent, false);
MuaViewHolder mvh = new MuaViewHolder(v, mListener);
return mvh;
}
#Override
public void onBindViewHolder(#NonNull MuaViewHolder holder, int position) {
MuaView currentView = mMuaView.get(position);
holder.mImageButton.setImageResource(currentView.getImageResource());
holder.mTextView1.setText(currentView.getText1());
}
#Override
public int getItemCount() {
return mMuaView.size();
}
public Filter getFilter() {
return MuaFilter;
}
private Filter MuaFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<MuaView> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(mMuaViewFull);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (MuaView item : mMuaViewFull) {
if (item.getText1().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mMuaView.clear();
mMuaView.addAll((ArrayList) results.values);
notifyDataSetChanged();
}
};
}
Answer for first question:
You could pass the position of the item to the new activity with intent.putExtra().
In the new activity you can read out the number with intent.getExtra() and setup your layout content as you want depending on the number you got.
This way you only have one Activity instead of many.
Activity 1
Intent intent = new Intent(this, Shima.class);
intent.putExtra("position_value", position);
startActivity(intent);
Activity 2
Intent intent = getIntent();
int position = intent.getIntExtra("position_value", 0); // 0 is the default value
// set a layout based on position with switch case or if...
switch (position){
case 1:
setContentView(R.layout.activity_card_one);
break;
case 2:
setContentView(R.layout.activity_card_two);
break;
....
Second question:
See here.
Basicaly the same way like
itemView.setOnClickListener(new View.OnClickListener() {...
You can set a image depending on what item has been clicked using something like this
private Integer images[] = {R.drawable.pic1, R.drawable.pic2, R.drawable.pic3}
and
imageView.setImageResource(images[position]);
(maybe position -1, not sure if first item in recyclerView is 1 or 0)
I just started app developing recently and stumbled upon a problem that I basically can't figure out : https://rubensousa.github.io/2016/08/viewpagercards
He instructed that on CardPagerAdapter.java in instantiateItem, I need to set the data according to the position. But how do I do it?
I want the first card to have a title of "FIRST CARD" while the second "SECOND CARD" and so on.. hope someone could help.
CardPagerAdapter.java
import android.support.v4.view.PagerAdapter;
import android.support.v7.widget.CardView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class CardPagerAdapter extends PagerAdapter implements CardAdapter {
private List<CardView> mViews;
private List<CardItem> mData;
private float mBaseElevation;
public CardPagerAdapter() {
mData = new ArrayList<>();
mViews = new ArrayList<>();
}
public void addCardItem(CardItem item) {
mViews.add(null);
mData.add(item);
}
public float getBaseElevation() {
return mBaseElevation;
}
#Override
public CardView getCardViewAt(int position) {
return mViews.get(position);
}
#Override
public int getCount() {
return mData.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View view = LayoutInflater.from(container.getContext())
.inflate(R.layout.fragment_adapter, container, false);
container.addView(view);
bind(mData.get(position), view);
CardView cardView = (CardView) view.findViewById(R.id.cardView);
if (mBaseElevation == 0) {
mBaseElevation = cardView.getCardElevation();
}
cardView.setMaxCardElevation(mBaseElevation * MAX_ELEVATION_FACTOR);
mViews.set(position, cardView);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
mViews.set(position, null);
}
private void bind(CardItem item, View view) {
TextView title = (TextView) view.findViewById(R.id.title);
TextView description = (TextView) view.findViewById(R.id.description);
Button button = (Button) view.findViewById(R.id.button);
title.setText(item.getTitle());
description.setText(item.getText());
button.setText(item.getButton());
}
}
I have pasted the whole class below from android studio. Im trying to create a gallery using image view and GridView.
package com.example.sc.loginappexercise;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
/**
* Created by sc on 16/03/2017.
*/
public class ImageAdapter extends BaseAdapter {
public Context context;
public int[] images = {
R.drawable.gallery1, R.drawable.gallery2,
R.drawable.gallery3, R.drawable.gallery4,
R.drawable.gallery5, R.drawable.gallery6,
R.drawable.gallery7, R.drawable.gallery8,
R.drawable.gallery9, R.drawable.gallery10,
};
public ImageAdapter(Context c){
context = c;
}
#Override
public int getCount() {
return images.length;
}
#Override
public Object getItem(int position) {
return images [position];
}
#Override
public long getItemId(int position) {
return 0;
}
}
**Below where it says setLayoutParams - it stays red and throws an error. cannot be referenced from a static context? **
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(context);
imageView.setImageResource(images[position]);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
ImageView.setLayoutParams(new GridView.LayoutParams(240, 240));
return imageView;
}
}
ImageView.setLayoutParams(new GridView.LayoutParams(240, 240)); => imageView.setLayoutParams(new GridView.LayoutParams(240, 240));
I => i
That's all!
I'm having issues to render a SVG Image in a TableView with a CellFactory.
Im using this code here, but it don't work, the svg image is scaled, but it don't resize.
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.shape.SVGPath;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
public class SVGTable extends Application {
private ObservableList<SVGExample> examples;
public static void main(String[] args) {
launch(args);
}
public SVGTable() {
examples = FXCollections.observableArrayList();
examples.addAll(new SVGExample(289),
new SVGExample(42),
new SVGExample(120));
}
#Override
public void start(Stage primaryStage) throws Exception {
AnchorPane pane = new AnchorPane();
Scene scene = new Scene(pane);
TableView<SVGExample> tableView = new TableView<>();
tableView.setMinWidth(500);
tableView.setMinHeight(400);
tableView.setItems(examples);
final TableColumn<SVGExample, Integer> ping = new TableColumn<>("Ping");
ping.setCellValueFactory(new PropertyValueFactory<>("ping"));
ping.setCellFactory(param -> new PingCell());
tableView.getColumns().add(ping);
pane.getChildren().add(tableView);
primaryStage.setScene(scene);
primaryStage.show();
}
public class SVGExample {
private final IntegerProperty ping = new SimpleIntegerProperty();
public SVGExample(int ping) {
setPing(ping);
}
public int getPing() {
return ping.get();
}
public IntegerProperty pingProperty() {
return ping;
}
public void setPing(int ping) {
this.ping.set(ping);
}
}
public class PingCell extends TableCell<SVGExample, Integer> {
private HBox hBox = new HBox();
private Label label;
private int oldValue;
private PingCell() {
label = new Label();
hBox.setAlignment(Pos.CENTER_LEFT);
oldValue = Integer.MIN_VALUE;
}
#Override
protected void updateItem(final Integer item, final boolean empty) {
if (item != null) {
label.setText(item + "ms");
int i = (item + 50) / 100;
if (i < 1)
i = 1;
if (4 < i)
i = 4;
if (i != oldValue) {
SVGPath svgPath1 = new SVGPath();
svgPath1.setContent("M149.2,8.3L127-13.9c42.4-42.4,98.7-65.8,158.5-65.8c59.8,0,116.1,23.4,158.5,65.8L421.8,8.3c-36.5-36.5-84.9-56.6-136.3-56.6C234.1-48.2,185.7-28.1,149.2,8.3z");
SVGPath svgPath2 = new SVGPath();
svgPath2.setContent("M190.9,50.1l-22.2-22.2C200-3.4,241.4-20.6,285.5-20.6c44.1,0,85.5,17.2,116.8,48.4l-22.2,22.2c-25.3-25.3-58.9-39.2-94.6-39.2C249.8,10.8,216.2,24.8,190.9,50.1z");
SVGPath svgPath3 = new SVGPath();
svgPath3.setContent("M232.7,91.8l-22.2-22.2c20.1-20.1,46.7-31.1,75-31.1s55,11.1,75,31.1l-22.2,22.2c-14.1-14.1-32.9-21.9-52.8-21.9C265.6,69.9,246.8,77.7,232.7,91.8z");
SVGPath svgPath4 = new SVGPath();
svgPath4.setContent("M285.5,98.1c-12.8,0-24.5,5.2-32.9,13.6l32.9,32.9l32.9-32.9C310,103.3,298.3,98.1,285.5,98.1z");
Shape s = SVGPath.union(SVGPath.union(SVGPath.union(svgPath1, svgPath2), svgPath3), svgPath4);
s.setScaleX(0.1);
s.setScaleY(0.1);
hBox.getChildren().clear();
hBox.getChildren().addAll(s, label);
}
setGraphic(hBox);
}
}
}
}
After run, it's look like this:
You can wrap the Shape in a Group to force re-size of layout bounds.
hBox.getChildren().addAll(new Group(s), label);
Scale is a type of transform and according to Javadocs:
Any transform, effect, or state applied to a Group will be applied to all children of that group. Such transforms and effects will NOT be included in this Group's layout bounds, however if transforms and effects are set directly on children of this Group, those will be included in this Group's layout bounds.