I'am new to android and I've a project of making a grid view of images and onclick on image it shows it , thats the ImageAdapter class code
public class ImageAdapter extends BaseAdapter{
private static LayoutInflater inflater = null;
private Activity activity;
private String mode = "";
int[] images=null ;
public ImageAdapter(Activity act, String mode , int[] images){
inflater = (LayoutInflater) act.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
activity = act;
this.mode = mode;
this.images= images ;
}
public ImageView getImage(int pos)
{
ImageView im = (ImageView) getItem(pos);
return im ;
}
#Override
public int getCount() {
return images.length;
}
#Override
public Object getItem(int position) {
return new Integer(images[position]);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
if(mode.equalsIgnoreCase("grid")){
if (view == null) {
view = inflater.inflate(R.layout.each_image1, null);
}
ImageView iv = (ImageView)view.findViewById(R.id.imageView);
iv.setImageResource(images[position]);
} else if(mode.equalsIgnoreCase("gallery")){
if (view == null) {
view = inflater.inflate(R.layout.each_image_gallery, null);
}
ImageView iv = (ImageView)view.findViewById(R.id.imageView);
iv.setImageResource(images[position]);
}
return view;
}
}
thats my grid activity
public class GridActivity extends Activity {
GridView grid = null;
public static ImageAdapter adapter1 ;
public static ImageAdapter adapter2 ;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.grid);
adapter1= new ImageAdapter(GridActivity.this, "grid" , Images.images1);
adapter2 = new ImageAdapter(GridActivity.this, "grid" , Images.images2);
Intent i = this.getIntent();
if (i!=null)
{
String unique = i.getExtras().getString("Unique");
if (unique.equals("islam"))
{
Toast.makeText(GridActivity.this, "islam", Toast.LENGTH_LONG).show();
grid = (GridView)findViewById(R.id.gridView1);
grid.setAdapter(adapter1);
}
if (unique.equals("natural"))
{
Toast.makeText(GridActivity.this, "nat", Toast.LENGTH_LONG).show();
grid = (GridView)findViewById(R.id.gridView1);
grid.setAdapter(adapter2);
}
}
grid.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int pos,long id) {
Intent i = new Intent(GridActivity.this, imgPrevActivity.class);
i.putExtra("selectedIntex", pos);
startActivity(i);
Toast.makeText(GridActivity.this,"ddd",Toast.LENGTH_LONG).show();
}
});
}
}
and this is the activity where it supposes to show any clicked on image
public class imgPrevActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.each_image1);
ImageView im = (ImageView)findViewById(R.id.imageView);
int pos = getIntent().getExtras().getInt("selectedIntex");
// ImageAdapter adapter = new ImageAdapter(imgPrevActivity.this, "image prev", null);
long Id= GridActivity.adapter1.getItemId(pos);
im.setImageResource((int) Id);
}
}
i've tried to get the position of image clicked on from the grid
then getting the Id from the position
and setting the image view to that ID
but it doesnt work !!
thats where the images are put in arrays
public class Images {
public static int[] images1 = {
R.drawable.buds, R.drawable.cherry_34,
R.drawable.clouds_2, R.drawable.coffee_beans_2,
R.drawable.death_valley_sand_dunes
};
public static int[] images2= {
R.drawable.morning_glory_pool,
R.drawable.pink_flowers, R.drawable.sun_flower,
R.drawable.sunrise_3, R.drawable.yellow_rose_3,
};
}
You have to pass your image resource id with intent. The list item id of adapter is useless because you have new Activity on the screen.
grid.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int pos,long id) {
Intent i = new Intent(GridActivity.this, imgPrevActivity.class);
i.putExtra("selectedIntex", grid.getAdapter().getItem(pos);
startActivity(i);
Toast.makeText(GridActivity.this,"ddd",Toast.LENGTH_LONG).show();
}
});
and change your code in your ImgPreviewActivity:
public class imgPrevActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.each_image1);
ImageView im = (ImageView)findViewById(R.id.imageView);
int pos = getIntent().getIntExtra("selectedIntex", 0);
im.setImageResource(pos);
}
}
I think it should work
Related
i want when i click image from gridview, image send to new layout (Details Image)
this is MainActivity
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GridView gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(this));
gridview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Intent i = new Intent(getApplicationContext(), SingleViewActivity.class);
i.putExtra("arg3", arg2);
startActivity(i);
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "okey", Toast.LENGTH_SHORT).show();
}
});
}
ImageAdapter
public class ImageAdapter extends BaseAdapter {
public static final String URL ="http://api.androidhive.info/json/movies/";
Context mContext;
int mThumbIds = 18;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return mThumbIds;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) { // if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(95, 95));
// imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(4, 4, 4, 4);
} else {
imageView = (ImageView) convertView;
}
Picasso.with(this.mContext)
.load(URL + position +".jpg")
// .placeholder(R.drawable.loader).error(R.drawable.ic_launcher).fit()
.into(imageView);
// imageView.setImageResource(mThumbIds[position]);
return imageView;
}
// references to our images }
in here i try get image from gridview, i try use intent, it's not work
Details Image
public class SingleViewActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.single_view);
Intent i = getIntent();
int position = i.getExtras().getInt("arg3");
ImageAdapter imageAdapter = new ImageAdapter(this);
ImageView imageView = (ImageView) findViewById(R.id.SingleView);
imageView.setImageResource(imageAdapter.getItemViewType(position));}}
can anyone help me
Two points:
Pass the URL of the image you selected from MainActivity to SingleViewActivity.
Use ImageLoader, and do not modify the width/heigth otherwise the memory cache will miss.
Others the cache will do everything for you.
I have a GridView with some images that when its clicked show in full screen.
But when I'm clicking image the app crash for Target must not be null :(
My Activity:
public class ArenaActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_arena);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
GridView gv = (GridView) findViewById(R.id.grid_view);
gv.setAdapter(new ArenaGridViewAdapter(this));
gv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Intent i = new Intent(ArenaActivity.this, ArenaViewActivity.class);
i.putExtra("position", position);
startActivity(i);
}
});
}
}
My Adapter:
public class ArenaGridViewAdapter extends BaseAdapter {
private Context context = null;
public ArenaGridViewAdapter(Context context) {
this.context = context;
}
public int[] arenaImgs = {
R.drawable.ic_arena_01,
R.drawable.ic_arena_02,
R.drawable.ic_arena_03,
R.drawable.ic_arena_04,
R.drawable.ic_arena_05,
R.drawable.ic_arena_06
};
#Override
public View getView(int position, View convertView, ViewGroup parent) {
SquaredImageView view = (SquaredImageView) convertView;
if (view == null) {
view = new SquaredImageView(context);
view.setScaleType(CENTER_CROP);
}
Picasso.with(this.context) //
.load(arenaImgs[position]) //
.placeholder(R.drawable.ic_placeholder) //
.error(R.drawable.ic_error) //
.fit() //
.into(view);
return view;
}
#Override
public int getCount() {
return arenaImgs.length;
}
#Override
public Object getItem(int arg0) {
return null;
}
#Override
public long getItemId(int arg0) {
return 0;
}
}
And Finally the Fullscreen:
public class ArenaViewActivity extends ActionBarActivity {
public int[] arenaImgs = {
R.drawable.ic_arena_01,
R.drawable.ic_arena_02,
R.drawable.ic_arena_03,
R.drawable.ic_arena_04,
R.drawable.ic_arena_05,
R.drawable.ic_arena_06
};
private ShareActionProvider mShareActionProvider;
private int urlshare;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_arena);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent i = getIntent();
int position = i.getExtras().getInt("position");
this.urlshare = position;
ImageView iv = (ImageView) findViewById(R.id.arena_full_view);
Picasso.with(getApplicationContext())
.load(arenaImgs[position])
.fit()
.centerCrop()
.into(iv);
}
}
The error log says that the Target null is in: Picasso.with(getApplicationContext())
I solved the problem. Was a error in layout of fullscreen.
Changed to: setContentView(R.layout.arena_full_view);
Thanks everyone.
I have a custom listView that is empty in first time , from other side i have an activity which contains a product details such as picture, title, model .in this activity there is a button , so when user press this button i want to add the product into my custom listView and shows all the product details there,
my listView is:
public class ListViewShoppingBasketActivity extends Activity {
BaseAdapter adapter;
ArrayList<SingleRow> list;
Context context;
String[] titles;
Bitmap[] images;
String[] descriptions;
TextView title;
TextView description;
ImageView image;
String rowTitles;
String rowDescription;
Bitmap rowImage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_view_shopping_basket_layout);
final ListView list = (ListView) findViewById(R.id.listView1);
list.setAdapter(new MyAdapter(this));
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int position,
long id) {
if (id == 0) {
} else if (id == 1) {
} else if (id == 2) {
} else if (id == 3) {
} else if (id == 4) {
}
}
});
}
class SingleRow {
String rowTitles;
String rowDescription;
Bitmap rowImage;
public SingleRow(String rowTitles, String rowDescription, Bitmap rowImage) {
this.rowTitles = rowTitles;
this.rowDescription = rowDescription;
this.rowImage = rowImage;
}
}
class MyAdapter extends BaseAdapter {
public MyAdapter(Context c) {
context = c;
list = new ArrayList<SingleRow>();
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int i) {
return list.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.shopping_basket_listview_row,
viewGroup, false);
title = (TextView) row.findViewById(R.id.textView1);
description = (TextView) row.findViewById(R.id.textView2);
image = (ImageView) row.findViewById(R.id.imageView1);
SingleRow temp = list.get(i);
title.setText(temp.rowTitles);
description.setText(temp.rowDescription);
image.setImageBitmap(temp.rowImage);
return row;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.list_view_shopping_basket, menu);
return true;
}
// // **********baraye add kardane item jadid be listview
public void addItems(View v) {
list.add(new SingleRow(rowTitles, rowDescription, rowImage));
adapter.notifyDataSetChanged();
}
}
and this is implementation of my button in other activity
b_add_to_cart = (Button) findViewById(R.id.b_add_to_cart);
b_add_to_cart.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(BarcodeDetailsActivity.this,
ListViewShoppingBasketActivity.class);
intent.putExtra("productID", proId);
intent.putExtra("productModel", proModel);
intent.putExtra("productTitle", proTitle);
intent.putExtra("productPictureUrl", mIcon11);
startActivity(intent);
}
});
my problem is , i dont know how and where i can assign my product details in my listview
You can put the next lines to the code of the ListViewShoppingBasketActivity:
Intent i = getIntent();
if (i.getExtras() != null){
int prodId = i.getExtras().getInt("productID");
....
}
You can put theese to an ArrayList, and use an BaseAdapter (http://developer.android.com/reference/android/widget/BaseAdapter.html) to display the data in the list.
i have EditText in second activity.so the value enter here will be added to the custom listview in first activity.
i first activity in list i have textview,checkbox and button(edit). here textview will be from second activity edittext data. so here if i click on edit then it navigates to second activity of that particular data .am getting all these now .. in second acitity i want to edit the textfield value .so it has to display the edited value with this data in listview of particular row.
public class MyApplication extends Application{
ArrayList<String> arryList = new ArrayList<String>();
String cardNumberData=null;
}
public class Second extends Activity{
EditText cardNumber;
String cardNumberReceived;
MyApplication app;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.editcredit);
cardNumberReceived = getIntent().getStringExtra("cardwithoutstring");
System.out.println("cardWithOutStringReceived"+cardNumberReceived);
app = ((MyApplication) getApplicationContext());
cardNumber =(EditText)findViewById(R.id.cardnumber);
cardNumber.setText(cardNumberReceived);
Button save =(Button)findViewById(R.id.save);
save.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
app.cardNumberData =cardNumber.getText().toString();
System.out.println("Gotcardname"+app.cardNumberData);
app.arryList.add(app.cardNumberData);
System.out.println("Array List Size "+app.arryList.size());
System.out.println("Array List Size "+app.cardTypeList.size());
Intent saveIntent =new Intent(Second.this,First.class);
startActivity(saveIntent);
}
});
}
}
public class First extends Activity{
protected ListItemsState[] mDeletedItemsStates;
protected ArrayAdapter<ListItemsState> mListAdapter;
protected ListView mFoldersListView;
protected Context mContext;
LayoutInflater lay;
MyApplication app;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.newcard);
app = ((MyApplication) getApplicationContext());
mDeletedItemsStates = (ListItemsState[])getLastNonConfigurationInstance();
if (mDeletedItemsStates == null) {
mDeletedItemsStates = new ListItemsState[app.arryList.size()];
for (int i = 0; i < app.arryList.size(); i++) {
mDeletedItemsStates[i] = new ListItemsState(app.arryList.get(i),i);
}
}
ArrayList<ListItemsState> gridItemsList = new ArrayList<ListItemsState>();
gridItemsList.addAll(Arrays.asList(mDeletedItemsStates));
mListAdapter = new DeletedItemsStateArrayAdapter(this, gridItemsList);
mFoldersListView.setAdapter(mListAdapter);
mFoldersListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
mFoldersListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Toast.makeText(getApplicationContext(), "am thelist",
Toast.LENGTH_LONG).show();
}
});
}
private static class ListItemsState {
private String produ = "";
private boolean checked = false;
private int position;
public ListItemsState(String produ, int position) {
this.position = position;
}
public String getProdu() {
return produ;
}
public int getPosition() {
return position;
}
public boolean isChecked() {
return checked;
}
public void setChecked(boolean checked) {
this.checked = checked;
}
}
/** Holds child views for one row. */
private static class ListItemsStateViewHolder {
private RadioButton checkBox;
private TextView produ;
private Button edit;
public TextView getProdu() {
return produ;
}
public Button getEdit() {
return edit;
}
public RadioButton getCheckBox() {
return checkBox;
}
}
private class DeletedItemsStateArrayAdapter extends
ArrayAdapter<ListItemsState> {
private int mSelectedPosition = -1;
private RadioButton mSelectedRB;
private LayoutInflater inflater;
public DeletedItemsStateArrayAdapter(Context context,
List<ListItemsState> sentItemsStateList) {
super(context, R.layout.customlist, R.id.card,
sentItemsStateList);
// Cache the LayoutInflate to avoid asking for a new one each time.
inflater = LayoutInflater.from(context);
}
#Override
public View getView(final int position, View convertView,
ViewGroup parent) {
final ListItemsState deletedItemsState = (ListItemsState) this
.getItem(position);
ListItemsStateViewHolder viewHolder = new ListItemsStateViewHolder();
// Create a new row view
if (convertView == null) {
convertView = inflater.inflate(R.layout.customlist, null);
convertView.setTag(new ListItemsStateViewHolder());
}
else {
viewHolder = (ListItemsStateViewHolder) convertView.getTag();
viewHolder.checkBox = viewHolder.getCheckBox();
viewHolder.produ = viewHolder.getProdu();
viewHolder.edit = viewHolder.getEdit();
}
viewHolder.produ = (TextView) convertView.findViewById(R.id.card);
viewHolder.checkBox = (RadioButton) convertView.findViewById(R.id.radioButton1);
viewHolder.edit=(Button)convertView.findViewById(R.id.editbutton);
try {
viewHolder.checkBox.setTag(deletedItemsState);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
viewHolder.edit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent edit =new Intent(getApplicationContext(), Second.class);
edit.putExtra("cardNumberSending",app.arryList.get(position));
edit.putExtra("Indexvalue",mFoldersListView.getItemIdAtPosition(position));
System.out.println("Index value ::::::::: "+mFoldersListView.getItemIdAtPosition(position));
startActivity(edit);
}
});
viewHolder.produ.setText(deletedItemsState.getProdu());
return convertView;
}
}
public Object onRetainNonConfigurationInstance() {
return mDeletedItemsStates;
}
}
You are adding the edited data to the ArrayList Again avoid it inside the Second Activity
app.cardNumberData = cardNumber.getText().toString();
if(arryList.indexOf(cardNumberReceived) != -1)
{
app.arryList.set(arryList.indexOf(cardNumberReceived), app.cardNumberData);
}else
{
app.arryList.add(app.cardNumberData);
}
In your second Activity do this onClick of save.
i created one grid view application, it's working fine now showing all images in grid view. now i am trying to display selected image in full screen, but i am getting error. my grid view images are downloaded in url link. my url link are stored in array list. how to solve this error?
error class name is FullImageActivity.class
error: imageAdapter1.GridViewConfig cannot be resolved or is not a field
error line :
imageView.setImageResource(imageAdapter1.GridViewConfig.getResim_list().get(position));
this is my coding:
public class FullImageActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.full_image);
// get intent data
Intent i = getIntent();
// Selected image id
int position = i.getExtras().getInt("id");
ImageAdapter imageAdapter1 = new ImageAdapter(this);
ImageView imageView = (ImageView) findViewById(R.id.full_image_view);
imageView.setImageResource(imageAdapter1.GridViewConfig.getResim_list().get(position));
}
}
ImageAdapter.class
public class ImageAdapter extends BaseAdapter implements ListAdapter {
private Context context;
public ImageAdapter(Context context) {
super();
this.context = context;
//Listeye image url si ekliyor
GridViewConfig.addImageUrls();
}
#Override
public int getCount() {
return GridViewConfig.getResim_list().size();
}
#Override
public Object getItem(int position) {
return GridViewConfig.getResim_list().get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if(convertView==null)
{
imageView=new ImageView(context.getApplicationContext());
//imageView.setImageURI(Uri.withAppendedPath(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, ""+ id));
imageView.setLayoutParams(new GridView.LayoutParams(100,100));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(5,5,5,5);
}else{
imageView=(ImageView)convertView;
}
imageView.setImageDrawable(LoadImageFromURL(GridViewConfig.getResim_list().get(position)));
return imageView;
}
//Internetten imageleri stream olarak cekip drawable olsurturuyor.
private Drawable LoadImageFromURL(String url)
{
try
{
InputStream is = (InputStream) new URL(url).getContent();
Drawable d = Drawable.createFromStream(is, "src");
return d;
}catch (Exception e) {
System.out.println(e);
return null;
}
}
}
GridViewconfig.class
public class GridViewConfig {
private static ArrayList<String> resim_list=new ArrayList<String>();
public static int[] getResim_list;
public static ArrayList<String> getResim_list() {
return resim_list;
}
public static void setResim_list(ArrayList<String> resim_list) {
GridViewConfig.resim_list = resim_list;
}
public static void addImageUrls(){
resim_list.add("http://igen.com/Images/Home/Client-Logo.png");
}
}
MyGridView.class
public class MyGridView extends Activity {
private GridView girGridView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
girGridView=(GridView) findViewById(R.id.gridView1_bir);
//ListView gibi buna da adapter set ediliyor.
girGridView.setAdapter(new ImageAdapter(getApplicationContext()));
girGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View view, int position,long arg3) {
// Sending image id to FullScreenActivity
Intent i = new Intent(getApplicationContext(), FullImageActivity.class);
// passing array index
i.putExtra("id", position);
startActivity(i);
}
});
}
}
I posted my full source code.....
First of all: GridViewConfig indeed is not a field of your ImageAdapter.
Second:
imageView.setImageResource(imageAdapter1.GridViewConfig.getResim_list().get(position));
it will not work: getResim_list() returns ArrayList, it contains String values NOT int
You can try change :
public class FullImageActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.full_image);
// get intent data
Intent i = getIntent();
// Selected image id
int position = i.getExtras().getInt("id");
ImageView imageView = (ImageView) findViewById(R.id.full_image_view);
GridViewConfig.addImageUrls();
imageView.setImageDravable(LoadImageFromURL(GridViewConfig.getResim_list().get(position)));
}
private Drawable LoadImageFromURL(String url) {
....
}
}
But in my opinion you should rewrite all your code. The main problem: the drawings must be loaded in a separate thread.