I wants to develop app in which user could choose multiple photos from gallery and can add caption like there is in whatsapp to add captions in multiple images
Anyone can help me in this.
If you looking for this,
You are on right place,
Here is the full solution I do for helping the beginners :
Layout UI Design
<ImageView
android:contentDescription="#string/app_name"
android:id="#+id/currentStreamImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"/>
<ImageView
android:id="#+id/selected_photo"
android:contentDescription="#string/app_name"
android:background="#null"
android:layout_margin="12dp"
android:layout_alignParentEnd="true"
android:src="#drawable/add_image_icon"
android:layout_width="40dp"
android:layout_height="40dp" />
<LinearLayout
android:layout_alignParentBottom="true"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:padding="10dp"
android:background="#drawable/fade_in_black"
android:id="#+id/captionArea"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/caption"
android:hint="#string/enter_caption_here"
android:textStyle="italic"
android:textColor="#android:color/white"
android:textColorHint="#android:color/white"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:src="#android:drawable/ic_menu_send" />
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="100dp"/>
</LinearLayout>
AddImageWithCaptionFragment
public class AddImageWithCaptionFragment extends Fragment implements ImageWithCaptionListener {
private ArrayList<ImgCap> imgCapArrayList = new ArrayList<>();
private PerfectAdapter adapter;
private RecyclerView recyclerView;
private ImageView select,mainStream;
private EditText captionEt;
private int mCurrentPosition;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.add_img_with_cap_layout, container, false);
recyclerView = (RecyclerView)view.findViewById(R.id.recyclerView);
select = (ImageView) view.findViewById(R.id.selected_photo);
mainStream = (ImageView) view.findViewById(R.id.currentStreamImage);
captionEt = (EditText) view.findViewById(R.id.caption);
select.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TedBottomPicker bottomSheetDialogFragment = new TedBottomPicker.Builder(getActivity())
.setOnMultiImageSelectedListener(new TedBottomPicker.OnMultiImageSelectedListener() {
#Override
public void onImagesSelected(ArrayList<Uri> uriList) {
imgCapArrayList.clear();
for (int i=0;i<uriList.size();i++) {
ImgCap imgCap = new ImgCap(i,"", uriList.get(i));
imgCapArrayList.add(imgCap);
}
adapter = new PerfectAdapter(getActivity(),imgCapArrayList,mainStream,AddImageWithCaptionFragment.this);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setAdapter(adapter);
}
})
.setPeekHeight(1600)
.showTitle(false)
.setCompleteButtonText("Done")
.setEmptySelectionText("No Select")
.create();
bottomSheetDialogFragment.show(getActivity().getSupportFragmentManager());
}
});
captionEt.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
imgCapArrayList.get(mCurrentPosition).setCaption(s.toString());
}
#Override
public void afterTextChanged(Editable s) {
}
});
return view;
}
#Override
public void imgCaptionCallBack(int position) {
mCurrentPosition = position;
captionEt.setText(imgCapArrayList.get(mCurrentPosition).getCaption());
}
}
Custom Adapter Class
public class PerfectAdapter extends RecyclerView.Adapter<PerfectAdapter.MyViewHolder>{
private LayoutInflater inflater;
private Context context;
private ArrayList<ImgCap> imgCapsList;
private ImageView mainStream;
private ImageWithCaptionListener mCallBack;
public PerfectAdapter(Context context,ArrayList<ImgCap> imgCapsList,ImageView mainStream,ImageWithCaptionListener mCallBack) {
inflater = LayoutInflater.from(context);
this.context = context;
this.imgCapsList = imgCapsList;
this.mainStream = mainStream;
this.mCallBack = mCallBack;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.image_item_layout, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(MyViewHolder holder,final int position) {
final ImgCap element = imgCapsList.get(holder.getAdapterPosition());
Glide.with(context).load(element.getImagePath()).into(holder.image);
Glide.with(context).load(imgCapsList.get(0).getImagePath()).into(mainStream);
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Glide.with(context).load(element.getImagePath()).into(mainStream);
mCallBack.imgCaptionCallBack(position);
}
});
}
#Override
public int getItemCount() {
return imgCapsList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder
{
ImageView image;
public MyViewHolder(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.image);
}
}
}
Listener Class For CallBack
public interface ImageWithCaptionListener {
void imgCaptionCallBack(int position);
}
Item layout
<RelativeLayout
android:background="#android:color/white"
android:padding="1dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:contentDescription="#string/app_name"
android:id="#+id/image"
android:scaleType="centerCrop"
android:layout_width="100dp"
android:layout_height="100dp" />
</RelativeLayout>
POJO Class
public class ImgCap {
private int position;
private String caption;
private Uri imagePath;
public ImgCap(int position, String caption, Uri imagePath) {
this.position = position;
this.caption = caption;
this.imagePath = imagePath;
}
public int getPosition() {
return position;
}
public String getCaption() {
return caption;
}
public Uri getImagePath() {
return imagePath;
}
public void setPosition(int position) {
this.position = position;
}
public void setCaption(String caption) {
this.caption = caption;
}
public void setImagePath(Uri imagePath) {
this.imagePath = imagePath;
}
}
Just Copy and Paste , Enjoy !!!
Related
I am unable to update a cardView in my app. I have a main activity which displays my card views which contain a textview, a seekbar, an imageView and a switch. I have an edit activity to edit cards and an add activity to add new cards. I have added an onClickListener on the Itemview in my ViewHolder class and inside it a startactivityforresult with intent for Transitioneditactivity. The transitioneditactivity is where the user can edit the values and press save to reflect the changes. However the changes are not reflected in the app. I was following the code from a book introduction to android application development and they have done the same thing yet theirs works and mine doesn't.
Heres the code
MainActivity
public class MainActivity extends AppCompatActivity {
public static final String TRANSITION_FAB = "fab_transition";
public static final String EXTRA_NAME = "name";
public static final String EXTRA_TYPE = "type";
public static final String EXTRA_SEEK = "seek";
public static final String EXTRA_UPDATE = "update";
public static final String EXTRA_DELETE = "delete";
private RecyclerView recyclerView;
private CardAdapter adapter;
private ArrayList<Card> cardsList=new ArrayList<>();
private String[] names;
private int[] type;
private String[] type_name;
private boolean[] switchstates;
private boolean[] seekstatus;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
names=getResources().getStringArray(R.array.device);
type_name = getResources().getStringArray(R.array.appliances);
initcards();
if(adapter==null){
adapter=new CardAdapter(this,cardsList);
}
recyclerView=findViewById(R.id.recyclerview);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
FloatingActionButton fab=findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Pair<View,String> pair=Pair.create(view.findViewById(R.id.fab),TRANSITION_FAB);
ActivityOptions options;
Activity act= MainActivity.this;
options= ActivityOptions.makeSceneTransitionAnimation(act,pair);
Intent transitionIntent= new Intent(act,TransitionAddActivity.class);
act.startActivityForResult(transitionIntent,adapter.getItemCount(),options.toBundle());
}
});
}
public void doSmoothScroll(int position){
recyclerView.smoothScrollToPosition(position);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==adapter.getItemCount()){
if(resultCode==RESULT_OK){
String name =data.getStringExtra(EXTRA_NAME);
int type=data.getIntExtra(EXTRA_TYPE,0);
boolean seek = data.getBooleanExtra(EXTRA_SEEK,false);
adapter.addCard(name,type,false,seek);
}else {
if (resultCode==RESULT_OK){
RecyclerView.ViewHolder viewHolder=recyclerView.findViewHolderForAdapterPosition(requestCode);
if(data.getExtras().getBoolean(EXTRA_UPDATE)){
String name = data.getStringExtra(EXTRA_NAME);
int type = data.getIntExtra(EXTRA_TYPE,0);
boolean seek = data.getBooleanExtra(EXTRA_SEEK,false);
viewHolder.itemView.setVisibility(View.INVISIBLE);
adapter.updateCard(name,type,seek,requestCode);
}
}
}
}
}
private void initcards() {
for(int i=0;i<2;i++){
Card card=new Card();
card.setId((long)i);
card.setName(names[i]);
card.setStatus(false);
card.setType(i);
cardsList.add(card);
}
}
}
Heres the Card Class
public class Card {
private long id;
private String name;
private int type;
private boolean status;
private boolean seekstatus;
public long getId() {
return id;
}
public boolean isSeekstatus() {
return seekstatus;
}
public void setSeekstatus(boolean seekstatus) {
this.seekstatus = seekstatus;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
}
The CardAdapter Class
public class CardAdapter extends
RecyclerView.Adapter<CardAdapter.ViewHolder>{
private static final String DEBUG_TAG = "CardAdapter";
public Context context;
public ArrayList<Card> cardsList;
public CardAdapter(Context context, ArrayList<Card> cardsList){
this.context=context;
this.cardsList=cardsList;
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
String name1 = cardsList.get(position).getName();
boolean switchstatus=cardsList.get(position).isStatus();
boolean seekstatus=cardsList.get(position).isSeekstatus();
int type=cardsList.get(position).getType();
TextView nametv= viewHolder.name;
nametv.setText(name1);
Switch device_switch = viewHolder.device_switch;
device_switch.setChecked(switchstatus);
SeekBar seek = viewHolder.seekbar;
if(seekstatus){
seek.setVisibility(View.VISIBLE);
}else {
seek.setVisibility(View.INVISIBLE);
}
}
#Override
public void onViewDetachedFromWindow(ViewHolder holder) {
super.onViewDetachedFromWindow(holder);
holder.itemView.clearAnimation();
}
#Override
public void onViewAttachedToWindow(ViewHolder holder) {
super.onViewAttachedToWindow(holder);
animateCircularReveal(holder.itemView);
}
public void animateCircularReveal(View view){
int centerX=0;
int centerY=0;
int startRadius=0;
int endRadius=Math.max(view.getWidth(),view.getHeight());
Animator animation=ViewAnimationUtils.createCircularReveal(view,centerX,centerY,startRadius,endRadius);
view.setVisibility(View.VISIBLE);
animation.start();
}
public void animateCircularDelete(final View view,final int list_position){
int centerX=view.getWidth();
int centerY=view.getHeight();
int startRadius=view.getWidth();
int endRadius=0;
Animator animation = ViewAnimationUtils.createCircularReveal(view,centerX,centerY,startRadius,endRadius);
animation.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
view.setVisibility(View.GONE);
cardsList.remove(list_position);
notifyItemRemoved(list_position);
}
});
}
public void addCard(String name,int type,boolean switchstatus,boolean seekstatus){
Card card=new Card();
card.setName(name);
card.setType(type);
card.setStatus(switchstatus);
card.setSeekstatus(seekstatus);
((MainActivity)context).doSmoothScroll(getItemCount());
cardsList.add(card);
notifyItemInserted(getItemCount());
}
public void updateCard(String name,int type,boolean seekstatus,int list_position){
cardsList.get(list_position).setName(name);
cardsList.get(list_position).setType(type);
cardsList.get(list_position).setSeekstatus(seekstatus);
notifyItemChanged(list_position);
}
public void deleteCard(View view,int list_position){
animateCircularDelete(view,list_position);
}
#Override
public int getItemCount() {
if(cardsList.isEmpty()){
return 0;
} else {
return cardsList.size();
}
}
#Override
public long getItemId(int position) {
return cardsList.get(position).getId();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
LayoutInflater li=LayoutInflater.from(viewGroup.getContext());
View v=li.inflate(R.layout.card_view_holder,viewGroup,false);
return new ViewHolder(v);
}
public class ViewHolder extends RecyclerView.ViewHolder{
private TextView name;
private Switch device_switch;
private ImageView device_image;
private SeekBar seekbar;
public ViewHolder(View v) {
super(v);
name=v.findViewById(R.id.name);
device_image=v.findViewById(R.id.device_image);
device_switch=v.findViewById(R.id.device_switch);
seekbar=v.findViewById(R.id.seekbar);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int requestCode= getAdapterPosition();
String name = cardsList.get(requestCode).getName();
int type = cardsList.get(requestCode).getType();
boolean seekstatus=cardsList.get(requestCode).isSeekstatus();
Intent transitionIntent=new Intent(context,TransitionEditActivity.class);
transitionIntent.putExtra(MainActivity.EXTRA_NAME,name);
transitionIntent.putExtra(MainActivity.EXTRA_TYPE,type);
transitionIntent.putExtra(MainActivity.EXTRA_SEEK,seekstatus);
transitionIntent.putExtra(MainActivity.EXTRA_UPDATE,false);
transitionIntent.putExtra(MainActivity.EXTRA_DELETE,false);
((AppCompatActivity)context).startActivityForResult(transitionIntent,requestCode);
}
});
device_switch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText((context),""+name.getText()+" is turned "+(device_switch.isChecked()?"On":"Off"),Toast.LENGTH_SHORT).show();
}
});
seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
Toast.makeText((context),""+name.getText()+"is set at "+i+"%",Toast.LENGTH_SHORT).show();
}
#Override
public void onStartTrackingTouch(SeekBar seekBar){
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
}
}
The EditActivity
public class TransitionEditActivity extends AppCompatActivity {
private EditText device_name;
private Spinner device_type;
private CheckBox seek_status;
ArrayAdapter<CharSequence> adapter;
private int type;
Button savebutton;
private Intent intent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_transition_edit);
device_name =findViewById(R.id.name);
device_type=findViewById(R.id.type);
seek_status=findViewById(R.id.cbintensity);
savebutton=findViewById(R.id.add);
adapter= ArrayAdapter.createFromResource(this,R.array.appliances,android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
device_type.setAdapter(adapter);
device_type.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int i, long l) {
type = i;
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
intent=getIntent();
String name=intent.getStringExtra(MainActivity.EXTRA_NAME);
type=intent.getIntExtra(MainActivity.EXTRA_TYPE,0);
boolean seek=intent.getBooleanExtra(MainActivity.EXTRA_SEEK,false);
device_name.setText(name);
device_name.setSelection(device_name.getText().length());
seek_status.setChecked(seek);
savebutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(TextUtils.isEmpty(device_name.getText().toString().trim())){
Toast.makeText(getApplicationContext(),"Enter a valid name",Toast.LENGTH_SHORT).show();
}else {
intent.putExtra(MainActivity.EXTRA_NAME,String.valueOf(device_name.getText()));
intent.putExtra(MainActivity.EXTRA_TYPE,type);
intent.putExtra(MainActivity.EXTRA_SEEK,seek_status.isChecked());
intent.putExtra(MainActivity.EXTRA_UPDATE,true);
setResult(RESULT_OK,intent);
supportFinishAfterTransition();
}
}
});
}
}
My activity main layout file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="kejriwal.shivam.automationcard.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="25dp"
android:layout_marginEnd="25dp"
android:elevation="6dp"
android:contentDescription="Add appliance"
android:id="#+id/fab"
android:clickable="true"
android:src="#android:drawable/ic_input_add"
android:tint="#android:color/white"
android:layout_height="wrap_content" />
</RelativeLayout>
the card layout file
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/card_layout"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:clickable="true"
android:layout_marginTop="10dp"
android:focusable="true"
android:elevation="6dp"
android:foreground="?android:attr/selectableItemBackground"
android:orientation="vertical"
card_view:cardBackgroundColor="#color/card"
card_view:cardCornerRadius="3dp"
>
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:id="#+id/linear"
android:orientation="vertical"
android:padding="3dp"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<ImageView
android:id="#+id/device_image"
android:src="#android:drawable/ic_input_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_centerVertical="true"
/>
<TextView
android:id="#+id/name"
android:text="Fan"
android:layout_marginStart="20dp"
android:layout_toRightOf="#+id/device_image"
android:layout_centerVertical="true"
android:layout_toEndOf="#+id/device_image"
android:textSize="20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Switch
android:id="#+id/device_switch"
android:layout_marginEnd="10dp"
android:layout_centerVertical="true"
android:layout_gravity="end"
android:layout_marginRight="20dp"
android:layout_width="wrap_content"
android:layout_alignParentEnd="true"
android:layout_height="wrap_content" />
</RelativeLayout>
<SeekBar
android:id="#+id/seekbar"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginEnd="90dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="10dp"
/>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
The Edit Layout file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_margin="20dp"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ImageView
android:layout_width="50dp"
android:id="#+id/device_image"
android:layout_gravity="center"
android:layout_height="50dp"
android:layout_marginBottom="20dp"
/>
<EditText
android:layout_width="200dp"
android:id="#+id/name"
android:layout_gravity="center"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
/>
<Spinner
android:layout_width="wrap_content"
android:prompt="#string/spinner_prompt"
android:layout_gravity="center"
android:layout_height="wrap_content"
android:id="#+id/type"
android:layout_marginBottom="20dp"
android:entries="#array/appliances"
/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Control Intensity"
android:id="#+id/cbintensity"
/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/add"
android:layout_width="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_height="wrap_content"
android:text="Save"/>
</RelativeLayout>
</LinearLayout>
you are binding your data inside viewholder in adapter...
your adapter should look like this...
public class BorderAdapter extends RecyclerView.Adapter<BorderAdapter.ViewHolder> {
private final Context context;
private final BorderSelectedListener borderSelectedListener;
public BorderAdapter(Context context, BorderSelectedListener borderSelectedListener) {
this.context = context;
this.borderSelectedListener = borderSelectedListener;
}
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(this.context).inflate(R.layout.frames_adapter_item, parent, false));
}
public void onBindViewHolder(final ViewHolder holder, #SuppressLint("RecyclerView") int position) {
Animation animation = AnimationUtils.loadAnimation(context,
(position > lastPosition) ? R.anim.left_to_right
: R.anim.right_to_left);
holder.itemView.startAnimation(animation);
holder.imageView.setBackground(context.getResources().getDrawable(R.drawable.stroke_invisible));
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
borderSelectedListener.onBorderSelected(holder.getAdapterPosition());
}
});
}
public int getItemCount() {
return serverData.getBorderFramesDetail().size();
}
public interface BorderSelectedListener {
void onBorderSelected(int position);
}
class ViewHolder extends RecyclerView.ViewHolder {
final ImageView imageView;
final ProgressBar progress_bar;
ViewHolder(View itemView) {
super(itemView);
this.imageView = itemView.findViewById(R.id.imageView);
this.progress_bar = itemView.findViewById(R.id.progress_bar);
}
}
}
Here, I have two recyclerview that has parentRecyclerViewAdapter and childRecyclerViewAdapter. Parent adapter has LinearLayoutManager.VERTICAL layout manager whereas Clild adapter has GridLayoutManager(mContext, 2) layout manager with itemDecoration.
When scrolling for the first time the RecyclerView scrolling is laggy and once the data is viewed the scrolling is smooth. Until the app instance is not completely removed the scrolling will be smooth and when the app reinitiate the scrolling is laggy again.
Please help me out to figure out this BUG!!
ParentRecyclerViewAdapter
public class RecyclerViewDataAdapter extends RecyclerView.Adapter<RecyclerViewDataAdapter.ItemRowHolder> {
private ArrayList<SectionDataModel> dataList;
private Context mContext;
private RecyclerListItemClick onListClick;
public RecyclerViewDataAdapter(Context context, ArrayList<SectionDataModel> dataList) {
this.dataList = dataList;
this.mContext = context;
onListClick = (RecyclerListItemClick) context;
}
#Override
public ItemRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
return new ItemRowHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.single_row_template_section, null));
}
#Override
public void onBindViewHolder(ItemRowHolder itemRowHolder, int i) {
ArrayList<SingleTemplateModel> templateModelArrayList = dataList.get(i).getTemplateModelArrayList();
String sectionName = dataList.get(i).getHeaderTitle();
itemRowHolder.itemTitle.setText(sectionName);
TemplateChooserAdapter itemListDataAdapter = new TemplateChooserAdapter(mContext, templateModelArrayList , dataList.get(i).getHeaderTitle());
itemRowHolder.recycler_view_list.setAdapter(itemListDataAdapter);
}
#Override
public int getItemCount() {
return (null != dataList ? dataList.size() : 0);
}
public class ItemRowHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView itemTitle;
private RecyclerView recycler_view_list;
private ItemRowHolder(View view) {
super(view);
this.itemTitle = view.findViewById(R.id.itemTitle);
this.recycler_view_list = view.findViewById(R.id.recycler_view_list);
this.recycler_view_list.setOnClickListener(this);
this.recycler_view_list.setHasFixedSize(true);
this.recycler_view_list.setLayoutManager(new GridLayoutManager(mContext, 2));
this.recycler_view_list.addItemDecoration(new SpacesItemDecoration(2 , 25 , false));
}
#Override
public void onClick(View v) {
onListClick.onRecyclerItemClicked(dataList.get(getAdapterPosition()).getHeaderTitle());
}
}
}
ChildRecyclerAdapter
public class TemplateChooserAdapter extends RecyclerView.Adapter<TemplateChooserAdapter.ViewHolder> {
private static final String TAG = TemplateChooserAdapter.class.getSimpleName();
private Context context;
private ArrayList<SingleTemplateModel> templateModelArrayList;
private OnTemplatesListClicked onListClick;
public TemplateChooserAdapter(Context context, ArrayList<SingleTemplateModel> templateModelArrayList, String sectionName) {
this.context = context;
this.templateModelArrayList = templateModelArrayList;
onListClick = (OnTemplatesListClicked) context;
AppUtils.showLog(TAG, "CorporateUserAdapter");
}
#Override
public TemplateChooserAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(
LayoutInflater.from(parent.getContext()).inflate(R.layout.single_row_template_chooser, parent, false)
);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.templateView.setImageResource(templateModelArrayList.get(position).getImage());
}
#Override
public int getItemCount() {
return templateModelArrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
ImageView templateView;
public ViewHolder(View itemView) {
super(itemView);
templateView = itemView.findViewById(R.id.template_view);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
templateModelArrayList.get(getAdapterPosition()).setShowIndicator(true);
onListClick.onTemplateClick(templateModelArrayList.get(getAdapterPosition())); // TODO send model when item clicked
}
}
}
Activity.java
private void recyclerViewJob() {
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
RecyclerViewDataAdapter adapter = new RecyclerViewDataAdapter(this, allSampleData);
recyclerView.setAdapter(adapter);
}
SectionDataModel.java
public class SectionDataModel {
private String headerTitle;
private ArrayList<SingleTemplateModel> templateModelArrayList;
public SectionDataModel() {
}
public SectionDataModel(String headerTitle, ArrayList<SingleTemplateModel> templateModelArrayList) {
this.headerTitle = headerTitle;
this.templateModelArrayList = templateModelArrayList;
}
public String getHeaderTitle() {
return headerTitle;
}
public void setHeaderTitle(String headerTitle) {
this.headerTitle = headerTitle;
}
public ArrayList<SingleTemplateModel> getTemplateModelArrayList() {
return templateModelArrayList;
}
public void setTemplateModelArrayList(ArrayList<SingleTemplateModel> templateModelArrayList) {
this.templateModelArrayList = templateModelArrayList;
}
}
SingleTemplateModel.java
public class SingleTemplateModel {
private String title;
private String skuName;
private int image;
private boolean showIndicator;
public SingleTemplateModel(String title, String skuName, int image, boolean showIndicator) {
this.title = title;
this.skuName = skuName;
this.image = image;
this.showIndicator = showIndicator;
}
public String getSkuName() {
return skuName;
}
public void setSkuName(String skuName) {
this.skuName = skuName;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getImage() {
return image;
}
public void setImage(int image) {
this.image = image;
}
public boolean isShowIndicator() {
return showIndicator;
}
public void setShowIndicator(boolean showIndicator) {
this.showIndicator = showIndicator;
}
}
single_row_template_section.xml
<?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="wrap_content"
android:orientation="vertical"
android:paddingTop="30dp"
android:clickable="true"
android:focusable="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/itemTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical"
android:text="Sample title"
android:textColor="#color/white"
android:textSize="20sp"
android:textStyle="bold"
android:paddingLeft="5dp"
android:paddingBottom="10dp"/>
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:orientation="horizontal" />
</LinearLayout>
single_row_template_chooser.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="280dp"
card_view:cardElevation="6dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/template_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:src="#mipmap/model_9" />
</RelativeLayout>
</android.support.v7.widget.CardView>
I think you can try to lazy load your images from resources. There are libraries like Picasso or Glide that will help you with that.
So it may look like this:
Picasso:
import com.squareup.picasso.Picasso;
...
public class TemplateChooserAdapter extends RecyclerView.Adapter<TemplateChooserAdapter.ViewHolder> {
...
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Picasso.with(holder.itemView.getContext()).load(templateModelArrayList.get(position).getImage()).into(holder.templateView);
}
...
}
I have a recyclerview which populates data from SQL database. Now each row in the recyclerview has a seekbar which when moved displays it's progress in a textview inside the same row. The problem is when I scroll the recyclerview up or down then return back to the first changed row, the seekbar is returned to its default position. How can I make it save the new position ? In normal activities/fragments I use lifecycle methods as "onPause" to save/restore the state. Here we have onAttachedToRecyclerView, I think it should solve my problem but I don't know exactly how.
EDIT : here is a full simple app files which I'm working on to test this problem.
MainActivity.class
public class MainActivity extends AppCompatActivity {
private List<Score> scoreList = new ArrayList<>();
private RecyclerView recyclerView;
private MyAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
mAdapter = new MyAdapter(scoreList);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
prepareScoreData();
}
private void prepareScoreData() {
Score score = new Score("title", 5);
scoreList.add(score);
for(int i= 0; i<1000; i++){
score = new Score("title", 5);
scoreList.add(score);
}
mAdapter.notifyDataSetChanged();
}
}
MyAdapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private List<Score> scoresList;
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView title, scoreView;
SeekBar seekbar;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
scoreView = (TextView) view.findViewById(R.id.score);
seekbar = (SeekBar) view.findViewById(R.id.seekbar);
}
}
public MyAdapter(List<Score> scoresList) {
this.scoresList = scoresList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
final Score score = scoresList.get(position);
holder.title.setText(score.getTitle());
if (!score.getProgressed()) {
holder.seekbar.setProgress(0) ;
} else {
holder.seekbar.setProgress(score.getSeekbarProgress());
}
holder.seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
holder.scoreView.setText(String.valueOf(i));
score.setSeekbarProgress(i);
score.setProgressed(true);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
#Override
public int getItemCount() {
return scoresList.size();
}
}
Score class
public class Score {
private String title;
int seekbarProgress;
boolean progressed;
public Score() {
}
public Score(String title,int seekbarProgress) {
this.title = title;
this.seekbarProgress = seekbarProgress;
}
public void setProgressed(boolean progressed) {
this.progressed = progressed;
}
public void setTitle(String title) {
this.title = title;
}
public void setSeekbarProgress(int seekbarProgress) {
this.seekbarProgress = seekbarProgress;
}
public String getTitle() {
return title;
}
public int getSeekbarProgress() {
return seekbarProgress;
}
public boolean getProgressed() {
return progressed;
}
}
MainActivity_Layout
<?xml version="1.0" encoding="utf-8"?>
<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.moaness.tut_recyclerview.MainActivity">
<!-- A RecyclerView with some commonly used attributes -->
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
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="wrap_content"
android:focusable="true"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="60dp"
android:paddingBottom="60dp"
android:layout_marginBottom="10dp"
android:clickable="true"
android:background="#f2f2f2"
android:orientation="vertical">
<TextView
android:id="#+id/title"
android:text="title"
android:textColor="#color/title"
android:textSize="16dp"
android:paddingTop="16dp"
android:textStyle="bold"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/score"
android:text="score"
android:layout_below="#+id/title"
android:textSize="16dp"
android:paddingBottom="16dp"
android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/score"
android:id="#+id/seekbar"
/>
</RelativeLayout>
If you are using recyclerview you need to maintain states of each row, means if you are checking using a condition(i.e. if) at any stage of recyclerview item(in recyclerview adapter class) then you need to handle else as well. I can send you a code snippet so you can have a good idea for recyclerview adapter.
public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ViewHolder> {
List<ViewHolder> holders = new ArrayList<ViewHolder>();
private ArrayList<ContactModel> arrayList = new ArrayList<>();
private Context context;
private LayoutInflater inflater;
public void clearAdapter() {
arrayList.clear();
notifyDataSetChanged();
}
public ContactsAdapter(Context context, ArrayList<ContactModel> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
public void setList(ArrayList<ContactModel> listSearch) {
this.arrayList = listSearch;
notifyItemRangeChanged(0, listSearch.size());
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.custom_row_for_contacts, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
holders.add(viewHolder);
return viewHolder;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final ContactModel current = this.arrayList.get(position);
holder.txtDriverName.setText(current.getName());
holder.txtDriverPhone.setText(current.getPhone());
if (current.getImgUrl().length() > 0) {
String urlLicenceThumb = UrlEndPoints.parentUrl + current.getImgUrl();
Glide.with(context).load(urlLicenceThumb).error(R.mipmap.ic_launcher).into(holder.imgDriver);
} else {
Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imgDriver);
}
}
public void delete(int position) {
arrayList.remove(position);
notifyItemRemoved(position);
}
#Override
public int getItemCount() {
return (null != arrayList ? arrayList.size() : 0);
}
class ViewHolder extends RecyclerView.ViewHolder {
private TextView txtDriverName, txtDriverPhone;
private CircleImageView imgDriver;
private Button btnInvite;
private CheckBox chkAdd;
public ViewHolder(View itemView) {
super(itemView);
chkAdd = (CheckBox) itemView.findViewById(R.id.chkAdd);
imgDriver = (CircleImageView) itemView.findViewById(R.id.imgDriver);
txtDriverName = (TextView)itemView.findViewById(R.id.txtDriverName);
txtDriverPhone = (TextView) itemView.findViewById(R.id.txtDriverPhone);
btnInvite = (Button) itemView.findViewById(R.id.btnInvite);
}
}
}
I have one recyclerview and this will display data in vertically. One row will display data in horizontally so i used another recyclerview. which is calling from first recyclerview's onBindViewHolder.
parent recylerview is working but when i am adding child recycler view. these methods are not calling (onCreateViewHolder, onBindViewHolder). Probably something issue in xml files.
parent xml:-
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
tools:context="com.catrackapp.catrack.MainActivity" >
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="VIDEO LATEST"
android:id="#+id/textView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:gravity="center" />
</RelativeLayout>
child xml which i am using in onCreateViewHolder as displaying row
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</android.support.design.widget.CoordinatorLayout>
and this xml is using by child recyclerview.
<?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="wrap_content"
android:paddingTop="5dp"
android:paddingBottom="5dp"
>
<com.google.android.youtube.player.YouTubeThumbnailView
android:id="#+id/thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/no_thumbnail"
android:adjustViewBounds="true" />
</LinearLayout>
These are code parent and child.
public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MyViewHolder> {
private List<Videos> moviesList;
// private ThumbnailListener thumbnailListener;
public class MyViewHolder extends RecyclerView.ViewHolder {
// public VideoView videoView;
//public ImageView imageView;
// YouTubeThumbnailView thumbnail;
RecyclerView recyclerView1;
public MyViewHolder(View view) {
super(view);
// videoView = (VideoView) view.findViewById(R.id.videoView);
// imageView = (ImageView) view.findViewById(R.id.imageView);
// thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
recyclerView1 = (RecyclerView) view.findViewById(R.id.recycler_view1);
// LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
// recyclerView1.setLayoutManager(layoutManager);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
recyclerView1.setLayoutManager(mLayoutManager);
}
}
public MoviesAdapter(List<Videos> moviesList) {
this.moviesList = moviesList;
//thumbnailListener = new ThumbnailListener();
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.test, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Videos movie = moviesList.get(position);
System.out.println("first = " + movie.getImage());
String url = movie.getVideo_url();
final String m = url.substring(url.lastIndexOf('/') + 1);
final String txt = movie.getPlain_text2();
System.out.println("url = "+m);
List<String> l = new ArrayList<String>();
l.add(m);
l.add(m);
l.add(m);
l.add(m);
l.add(m);
final MoviesAdapterHorizontal adapter = new MoviesAdapterHorizontal(l);
holder.recyclerView1.setAdapter(adapter);
// holder.recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
adapter.notifyDataSetChanged();
}
#Override
public int getItemCount() {
return moviesList.size();
}
private final class ThumbnailListener implements
YouTubeThumbnailView.OnInitializedListener,
YouTubeThumbnailLoader.OnThumbnailLoadedListener {
#Override
public void onInitializationSuccess(
YouTubeThumbnailView view, YouTubeThumbnailLoader loader) {
loader.setOnThumbnailLoadedListener(this);
// thumbnailViewToLoaderMap.put(view, loader);
// view.setImageResource(R.drawable.loading_thumbnail);
String videoId = (String) view.getTag();
loader.setVideo(videoId);
}
#Override
public void onInitializationFailure(
YouTubeThumbnailView view, YouTubeInitializationResult loader) {
view.setImageResource(R.drawable.no_thumbnail);
}
#Override
public void onThumbnailLoaded(YouTubeThumbnailView view, String videoId) {
}
#Override
public void onThumbnailError(YouTubeThumbnailView view, YouTubeThumbnailLoader.ErrorReason errorReason) {
view.setImageResource(R.drawable.no_thumbnail);
}
}
}
//Horizontal images view.
public class MoviesAdapterHorizontal extends RecyclerView.Adapter<MoviesAdapterHorizontal.MyViewHolder> {
private List<String> moviesList;
private ThumbnailListener thumbnailListener;
public class MyViewHolder extends RecyclerView.ViewHolder {
YouTubeThumbnailView thumbnail;
public MyViewHolder(View view) {
super(view);
thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
}
}
public MoviesAdapterHorizontal(List<String> moviesList) {
this.moviesList = moviesList;
thumbnailListener = new ThumbnailListener();
System.out.println("called size = "+this.moviesList.size());
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.hotrow, parent, false);
System.out.println("onCreateViewHolder called");
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
final String url = moviesList.get(position);
System.out.println("rahul url" + url);
final String m = url.substring(url.lastIndexOf('/') + 1);
System.out.println("url = "+m);
holder.thumbnail.setTag(m);
holder.thumbnail.initialize("AIzaSyDW-sxPUqy2rD6ZWs3vTNb0jKEKA21RjrY", thumbnailListener);
holder.thumbnail.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), FullscreenDemoActivity.class);
intent.putExtra("url", m);
intent.putExtra("txt", "");
startActivity(intent);
}
});
}
#Override
public int getItemCount() {
System.out.println("moviesList 2 size = "+this.moviesList.size());
return this.moviesList.size();
}
private final class ThumbnailListener implements
YouTubeThumbnailView.OnInitializedListener,
YouTubeThumbnailLoader.OnThumbnailLoadedListener {
#Override
public void onInitializationSuccess(
YouTubeThumbnailView view, YouTubeThumbnailLoader loader) {
loader.setOnThumbnailLoadedListener(this);
String videoId = (String) view.getTag();
loader.setVideo(videoId);
}
#Override
public void onInitializationFailure(
YouTubeThumbnailView view, YouTubeInitializationResult loader) {
view.setImageResource(R.drawable.no_thumbnail);
}
#Override
public void onThumbnailLoaded(YouTubeThumbnailView view, String videoId) {
}
#Override
public void onThumbnailError(YouTubeThumbnailView view, YouTubeThumbnailLoader.ErrorReason errorReason) {
view.setImageResource(R.drawable.no_thumbnail);
}
}
}
kindly help me. i am trying to fix it last 4 days. but now able to fix.
UPDATE:-
i used it and now child all methods are calling but layout is not displaying.
MoviesAdapterHorizontal adapter = new MoviesAdapterHorizontal(l);
holder.recyclerView1.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false));
holder.recyclerView1.setAdapter(adapter);
adapter.notifyDataSetChanged();
i saw below error in log
04-21 11:40:50.571 27006-27006/com.androidbelieve.drawerwithswipetabs W/ResourcesManager: getTopLevelResources: com.androidbelieve.drawerwithswipetabs for user 0
In CoordinatorLayout layout ,you cannot set RecyclerView height to android:layout_height="wrap_content"
try to set
android:layout_height="200dp"
OR
android:layout_height="match_parent"
This question already has answers here:
How to create RecyclerView with multiple view types
(23 answers)
Closed 6 years ago.
I am getting data in jSON. Data contains images url. I am trying to display images in below layouts.
1Image
2Image
3Image 4Image 5Image 6Image 7image
8Image 9Image 10Image 11Image 12image
13image 14image 15image 16image 17image
.... .... ..... ...... .....
So First two image will be in vertically. Other 5 images in horizontal scroll view and so on.
So i am using RecyclerView with vertical orientation. but i am not able to creating the logic so images will be display above format.
please anyone guide me.
update:-
//Horizontal images view.
public class MoviesAdapterHorizontal extends RecyclerView.Adapter<MoviesAdapterHorizontal.MyViewHolder> {
private List<String> moviesList;
// private ThumbnailListener thumbnailListener;
public class MyViewHolder extends RecyclerView.ViewHolder {
// YouTubeThumbnailView thumbnail;
ImageView imageView2;
public MyViewHolder(View view) {
super(view);
// thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
imageView2 = (ImageView) view.findViewById(R.id.imageView2);
}
}
public MoviesAdapterHorizontal(List<String> moviesList) {
this.moviesList = moviesList;
// thumbnailListener = new ThumbnailListener();
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.hotrow2, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
final String url = moviesList.get(position);
System.out.println("movie url = " + url);
final String m = url.substring(url.lastIndexOf('/') + 1);
System.out.println("url = "+m);
int w = BasicDeviceInfo.getWidth(getActivity());
// int h = BasicDeviceInfo.getHeight(getActivity());
LinearLayout.LayoutParams lParams =
new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
w/3);
AQuery aq = new AQuery(holder.imageView2);
aq.id(holder.imageView2).image("http://x.x.x.231/news-flicks/uploads/home/tulips_e84aa48cee1a2a25aef001cd74152663.jpg", true, true, 0,
R.drawable.no_thumbnail);
holder.imageView2.setLayoutParams(lParams);
// holder.thumbnail.setLayoutParams(lParams);
/* holder.thumbnail.setTag(m);
holder.thumbnail.initialize("AIzaSyDW-sxPUqy2rD6ZWs3vTNb0jKEKA21RjrY", thumbnailListener);
holder.thumbnail.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), FullscreenDemoActivity.class);
intent.putExtra("url",m);
intent.putExtra("txt", "");
startActivity(intent);
}
});*/
}
#Override
public int getItemCount() {
return moviesList.size();
}
private final class ThumbnailListener implements
YouTubeThumbnailView.OnInitializedListener,
YouTubeThumbnailLoader.OnThumbnailLoadedListener {
#Override
public void onInitializationSuccess(
YouTubeThumbnailView view, YouTubeThumbnailLoader loader) {
loader.setOnThumbnailLoadedListener(this);
String videoId = (String) view.getTag();
loader.setVideo(videoId);
}
#Override
public void onInitializationFailure(
YouTubeThumbnailView view, YouTubeInitializationResult loader) {
view.setImageResource(R.drawable.no_thumbnail);
}
#Override
public void onThumbnailLoaded(YouTubeThumbnailView view, String videoId) {
}
#Override
public void onThumbnailError(YouTubeThumbnailView view, YouTubeThumbnailLoader.ErrorReason errorReason) {
view.setImageResource(R.drawable.no_thumbnail);
}
}
}
horizontal xml:-
<?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="wrap_content"
android:orientation="vertical"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/imageView2"
android:src="#drawable/no_thumbnail"/>
</LinearLayout>
i am calling it parent recycle view onBindViewHolder()
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
Videos movie = moviesList.get(position);
System.out.println("Image = " + movie.getImage());
int w = BasicDeviceInfo.getWidth(getActivity());
// int h = BasicDeviceInfo.getHeight(getActivity());
if(position < 2) {
final List<String> lst = new ArrayList<String>();
lst.add(movie.getVideo_url());
lst.add(movie.getVideo_url());
lst.add(movie.getVideo_url());
lst.add(movie.getVideo_url());
lst.add(movie.getVideo_url());
final MoviesAdapterHorizontal adapter = new MoviesAdapterHorizontal(lst);
holder.recyclerView2.setAdapter(adapter);
adapter.notifyDataSetChanged();
Now my horizontal onBindViewHolder is calling and able to see log messages. But ImageView is not displaying. i think it is hiding or overlapping
See onto this Answer for how to make different layout item in RecyclerView
For first two element layout file containing ImageView
For rest item view I will suggest take Horizontal RecyclerView as item
My Custom view for Horizontal RecyclerView
public class DocumentViewDynamic extends LinearLayout {
private static final String LOG_TAG = DocumentViewDynamic.class.getSimpleName();
private final String titleStr;
private OnDocumentItemClicked callBack;
public void updateImage(Bitmap bitmap, int postionOfView) {
Log.e(LOG_TAG, "updateImage: ");
documentAdapter.setImageFromCamera(bitmap, postionOfView);
}
public interface OnDocumentItemClicked {
void onDocumentItemClicked(View v, int position);
}
public void setItemClickedListener(OnDocumentItemClicked callBack) {
this.callBack = callBack;
}
#Bind(R.id.title)
TextView title;
#Bind(R.id.img_add)
FloatingActionButton imgAdd;
private DocumentAdapter documentAdapter;
private final Context context;
#Bind(R.id.rv_document)
RecyclerView rvDocument;
#OnClick(R.id.img_add)
public void addDummyImage() {
documentAdapter.addSingelDummyImage();
rvDocument.scrollToPosition(documentAdapter.getItemCount() - 1);
}
public DocumentViewDynamic(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.DocumentViewDynamic, 0, 0);
try {
titleStr = ta.getString(R.styleable.DocumentViewDynamic_titleDoc);
} finally {
ta.recycle();
}
init();
}
public ArrayList<DocumentModel> getAllImageData() {
return documentAdapter.getImageData();
}
private void init() {
setOrientation(VERTICAL);
View view = LayoutInflater.from(context).inflate(R.layout.compund_view_document, this);
ButterKnife.bind(this, view);
if (!TextUtils.isEmpty(titleStr))
title.setText(titleStr);
initRecyclerView();
}
private void initRecyclerView() {
rvDocument.setLayoutManager(new LinearLayoutManager(context, HORIZONTAL, false));
ArrayList<DocumentModel> documentModels = new ArrayList<>();
documentAdapter = new DocumentAdapter(documentModels);
rvDocument.setAdapter(documentAdapter);
}
public class DocumentAdapter extends RecyclerView.Adapter<DocumentAdapter.DocViewHolder> {
public ArrayList<DocumentModel> getImageData() {
return documentModels;
}
private ArrayList<DocumentModel> documentModels = new ArrayList<>();
public DocumentAdapter(ArrayList<DocumentModel> documentModels) {
this.documentModels = documentModels;
if (documentModels.size() == 0)
documentModels.add(new DocumentModel());
}
#Override
public DocViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_compund_document, parent, false);
return new DocViewHolder(view);
}
#Override
public void onBindViewHolder(final DocViewHolder holder, int position) {
if (documentModels.get(position).getBitmap() == null) {
holder.imgDocument.setImageResource(R.drawable.camera);
holder.imgBtnDelete.setVisibility(GONE);
} else {
holder.imgDocument.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
holder.imgDocument.setScaleType(ImageView.ScaleType.FIT_XY);
holder.imgDocument.setImageBitmap(documentModels.get(position).getBitmap());
holder.imgBtnDelete.setVisibility(VISIBLE);
}
holder.itemView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
callBack.onDocumentItemClicked(DocumentViewDynamic.this, holder.getAdapterPosition());
}
});
holder.imgBtnDelete.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (holder.getAdapterPosition() == 0 && documentModels.size() == 1) {
documentModels.get(holder.getAdapterPosition()).setBitmap(null);
} else {
documentModels.remove(holder.getAdapterPosition());
}
notifyDataSetChanged();
}
});
}
#Override
public int getItemCount() {
return (documentModels != null && documentModels.size() > 0) ? documentModels.size() : 0;
}
public void setImageFromCamera(Bitmap imageFromCamera, int postionOfView) {
documentModels.get(postionOfView).setBitmap(imageFromCamera);
notifyDataSetChanged();
}
public class DocViewHolder extends RecyclerView.ViewHolder {
#Bind(R.id.img_document)
ImageView imgDocument;
#Bind(R.id.img_btn_delete)
ImageView imgBtnDelete;
public DocViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
public void addSingelDummyImage() {
if (documentModels.get(documentModels.size() - 1).getBitmap() != null) {
documentModels.add(new DocumentModel());
notifyDataSetChanged();
} else {
Snackbar.make(rvDocument, "Please Add image ", Snackbar.LENGTH_LONG).show();
}
}
}
}
layout file for compound view
<?xml version="1.0" encoding="utf-8"?>
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Title"
android:textColor="#3399ff"
android:textSize="15dp"
android:textStyle="normal" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_document"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="#+id/img_add" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/img_add"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_centerVertical="true"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:src="#drawable/fab_plus_bg" />
</RelativeLayout>
Inflate this compound view as item in Vertical RecyclerView