RecyclerView scroll lags with simple items - android

i have a simple recycler view which contains card views with only 1 imageView inside, which is loading from resources, but i have strong lags while scrolling anyway, i tried recycler.setHasFixedSize(true) but it doesn't help.
Acitivity code
public class MainActivity extends AppCompatActivity {
private final int[] drawables = {
R.drawable.nxt_bluetooth_dongle,
R.drawable.color_sensor,
R.drawable.connector_cabels,
R.drawable.e_motor,
R.drawable.energy_storage,
R.drawable.energy_display,
R.drawable.gyroscopic_sensor,
R.drawable.intelligent_nxt_brick,
R.drawable.keyfob_transponder,
R.drawable.light_sensor,
R.drawable.motion_sensor,
R.drawable.nxt_ir_receiver,
R.drawable.nxt_light_sensor,
R.drawable.nxt_servo_motor,
R.drawable.nxt_sound_sensor,
R.drawable.nxt_touch_sensor,
R.drawable.nxt_ultrasonic_sensor,
R.drawable.rf_id_sensor,
R.drawable.solar_panel,
R.drawable.tilt_sensor,
R.drawable.temperature_sensor,
R.drawable.usb_hub
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recycler = (RecyclerView) findViewById(R.id.recycler);
MyAdapter adapter = new MyAdapter(drawables);
recycler.setAdapter(adapter);
recycler.setLayoutManager(new GridLayoutManager(this, 3));
}
private class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder> {
private int[] drawables;
private MyAdapter(int[] drawables) {
this.drawables = drawables;
}
#Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.lego_recycler_item, null, false);
return new MyHolder(view);
}
#Override
public void onBindViewHolder(MyHolder holder, int position) {
holder.legoImage.setImageResource(drawables[position]);
}
#Override
public int getItemCount() {
return drawables.length;
}
class MyHolder extends RecyclerView.ViewHolder {
ImageView legoImage;
MyHolder(View itemView) {
super(itemView);
legoImage = (ImageView) itemView.findViewById(R.id.legoImage);
legoImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, LegoDetailActivity.class);
intent.putExtra(LegoDetailActivity.EXTRA_DRAWABLE_ID, drawables[getAdapterPosition()]);
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(
MainActivity.this, legoImage, "legoDetail"
);
startActivity(intent, options.toBundle());
}
});
}
}
}
}
Activity xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#e0e0e0"
tools:context="com.lol.legomindstorms.MainActivity">
</android.support.v7.widget.RecyclerView>
Recycler item xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardUseCompatPadding="true"
app:cardCornerRadius="0dp">
<ImageView
android:id="#+id/legoImage"
android:layout_width="115dp"
android:layout_height="115dp"
android:transitionName="legoDetail" />
</android.support.v7.widget.CardView>

Well as Per my Experience i think the problem is in loading multiple Images
As android do have problem with loading lots of images in memory ,
as android by default does not allow lot of gc memeory size ,
Check out your logs do you get a gc memory over load error
or something similar to that
1.you can Also try chaning the heap size
2.Try using an external library it is always said never reinvent the wheel
try glide or piccaso
3.Try clearing bitmap memory by your self
PS: i am not that writter so please dont mind if my wording were bad but i have dealt with these issues a lot so i am very familar with this problem

Related

Android FlexBox Layout shows only fixed number of lines

I'm trying to build a word-to-word RTL language ebook application. The data for the ebook is stored in an Sqlite database. After vigorous searching I found Flexbox layout suitable to my need in order to display my data in my required format. The following link helped me out: Android GridLayout with dynamic number of columns per row But the issue is that if the data passed in the view is large, then partial data is being displayed. If the data passed is small, then i have no issues at all.
Here is the adapter code:
public class VerseAdapter extends RecyclerView.Adapter<VerseAdapter.ViewHolder> {
private List<verseItem> items;
private Context context;
wordsAdapter sAdapter;
GridLayoutManager layoutManager;
public VerseAdapter(List<verseItem> items, Context context) {
this.items = items;
this.context = context;
}
// This method is used to attach
// custom layout to the recycler view
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View vw = LayoutInflater.from(parent.getContext()).inflate(R.layout.verse_row, parent, false);
return new ViewHolder(vw);
}
// This method is used to set the action
// to the widgets of our custom layout.
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
verseItem item = items.get(position);
ArrayList<wordsModel> models = new ArrayList<>(item.getWordsModelList());
String ayahnum = "" + item.getAyah();
holder.ayah.setText(ayahnum);
holder.verses_telugu.setText(item.getVerses_telugu());
// FlexboxLayoutManager code:
FlexboxLayoutManager layoutManager = new FlexboxLayoutManager(context);
layoutManager.setFlexDirection(FlexDirection.ROW_REVERSE);
layoutManager.setJustifyContent(JustifyContent.FLEX_START);
ViewHolder.wordsrecyclerView.setLayoutManager(layoutManager);
sAdapter = new wordsAdapter(models);
ViewHolder.wordsrecyclerView.setAdapter(sAdapter);
sAdapter.notifyItemChanged(position);
holder.setIsRecyclable(false);
}
#Override
public int getItemCount() {
return items.size();
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView ayah;
TextView verses_telugu;
public static RecyclerView wordsrecyclerView;
public ViewHolder(View itemView) {
super(itemView);
ayah = itemView.findViewById(R.id.ayah);
verses_telugu = itemView.findViewById(R.id.telugu_line);
wordsrecyclerView = itemView.findViewById(R.id.words_RV_id);
}
}
}
Here is my layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/ayah"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_margin="5dp"
android:textAlignment="viewStart"
android:textColor="#27A82C"
android:textSize="18sp"
android:textStyle="bold" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/words_RV_id"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/telugu_line"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_margin="5dp"
android:textAlignment="textStart"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
This is how the final result show actually look like:
This is how my app looks like:
Now if you notice from the screenshots, the data that i'm trying to display is same. But in my app, not all words are being displayed as you can notice.
Another thing i have noticed is for larger data if the screen orientation is vertical the maximum lines i can see is 10 and if it is horizontal i can see 6 lines at max. These number of lines are fixed for all the places where the data is large. If the data is smaller it is displayed in the exact number of lines required and as mentioned earlier I have no issues at all.
Hoping someone helps me out soon. Thanks in advance. (:

How do I not recycle only the first 2 views of my recyclerview or any items?

I am using a recyclerview for displaying and broadcasting videos of users. However, when I scroll through the recycler view, I see my first view, which has my video gets recycled hence why it's not visible to other users. Is there a way I can make sure that the first view is not recycled so I dont have to worry about my video view getting resetrecycled every single time I scroll through my list?
Here's my code :
In my fragment...
...
<android.support.v7.widget.RecyclerView
android:id="#+id/videoList"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="invisible"
app:layout_constraintBottom_toTopOf="#+id/myButtonContainer"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/myoldContainer">
...
and the corresponding adapter...
public class GroupAdapter extends RecyclerView.Adapter<GroupAdapter.myViewHolder> {
private CopyOnWriteArrayList<Person> persons;
private Context mContext;
public GroupAdapter(#NonNull final CopyOnWriteArrayList<Person> persons , Context context) {
this.persons = persons;
this.mContext= context;
for (Person person : this.persons) {
//get names
}
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View layout = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_person, parent, false);
final MyViewHolder viewHolder = new MyViewHolder(layout);
return viewHolder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
final Person person = person.get(position);
final Participant participant = person.getParticipant();
if (person.getName() != null) {
holder.personName.setText(person.getName());
}
if (person.getImage() != null) {
holder.personImage.setImageBitmap(person.getImage());
} else {
holder.personImage.setImageResource(R.drawable.default_profile);
}
holder.personImage.setVisibility(View.INVISIBLE);
holder.personImage.setVisibility(View.VISIBLE);
final VideoView videoView;
if (participant.isMe) {
videoView = participant.videoStreamer.videoView;
} else {
videoView = participant.videoPlayer.videoView;
}
if (holder.personVideo.getChildCount() != 0) {
holder.personVideo.removeAllViews();
}
if (videoView.getParent() != null) {
ViewGroup parent = (ViewGroup) videoView.getParent();
parent.removeView(videoView);
}
holder.personVideo.addView(videoView, myViewHolder.videoLayoutParams);
if (person.isVideoPaused()) {
holder.personVideo.setVisibility(View.INVISIBLE);
holder.personImage.setVisibility(View.VISIBLE);
} else {
holder.personVideo.setVisibility(View.VISIBLE);
holder.personImage.setVisibility(View.INVISIBLE);
}
}
#Override
public int getItemCount() {
return persons.size();
}
public static final class MyViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.personVideo)
public ViewGroup personVideo;
#BindView(R.id.personImage)
public ImageView personImage;
#BindView(R.id.personName)
public TextView personName;
protected static FrameLayout.LayoutParams videoLayoutParams = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
);
public MyViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
Here's how I am setting it in my fragment:
LinearLayoutManager manager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
videoAdapter = new VideoAdapter(myHelper.getPeople(), getContext());
videoList.setLayoutManager(manager);
videoList.setAdapter(videoAdapter);
item_person:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="0dp"
android:background="#drawable/person_border"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
android:id="#+id/personContainer"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent">
<FrameLayout
android:id="#+id/personVideo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black" />
<ImageView
android:id="#+id/personImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black"
android:src="#drawable/default_profile" />
<TextView
android:id="#+id/personName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#AA555555"
android:gravity="center_horizontal|bottom"
android:textColor="#color/green"
android:textSize="12sp"
android:lines="1"
android:ellipsize="end"
tools:text="androiduser#gmail.com"
android:layout_alignParentBottom="true" />
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
fragment with recycle view: xml
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<RelativeLayout>
....
</RelativeLayout>
<include containers>...</include>
...
<android.support.v7.widget.RecyclerView
android:id="#+id/personList"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="invisible"
>
</android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
I don't think that "not recycling" the video view will actually stop it from being destroyed when you scroll. It's not the recycling is the problem but the view unbinding.
I think such complex component such as VideoView should not be inside the RecyclerView at all.. You can try adding it as a static content on top, which most likely will solve the issue. You can use a NestedScrollView for that. Take a look here: Recyclerview inside scrollview- How to scroll whole content?
If you still think you want to keep it in the RecyclerView and disable the recycling, do the following.
Create a separate view type for your video view items. Here is an example:
https://stackoverflow.com/a/26573338/3086818. Treat your video view item as a header view from the example.
Once you do this, there is a RecycledViewPool class which manages the recycling of items inside a RecyclerView. You can tell it which views to recycle and which not. By default it recycles all views. To disable recycling for your video view items use your new view type like this:
recyclerView.getRecycledViewPool().setMaxRecycledViews(TYPE_VIDEO_VIEW, 0);
where TYPE_VIDEO_VIEW is the new type that you created using the previous example. The number 0 tells the RecyclerView how many items to recycle - in this case it's 0, meaning "do not recycle". More info about this here: https://stackoverflow.com/a/36313437/3086818.
I hope this helps.. Good luck!
The answer is yes, you can actually do that.
Since you said "The first item" so you simply add a check.
if(position == 0)
{
holder.setIsRecyclable(false); //This line prevents the row from recycling
}

CoordinatorLayout/AppBarLayout interfere with RecyclerView scrollToPosition(bottom scrolling)

This question has been asked many times but it just doesn't seem to have a solution that fits my requirement.
I have a Recipe that has instructions. Each instruction is ordered in a RecyclerView. The order must be from top to bottom. It cannot be reversed like many answers to this question.
I have an Add button that when clicked a new item is added at the bottom of the list. I need to scroll to the new item after the insert. So I employed the following code in the button's onClick event:
mRecyclerAdapter.addItem(newInstruction);
mRecyclerView.smoothScrollToPosition(mRecyclerAdapter.getItemCount() - 1);
This scrolls to the second last item because in the adapter's addItem() method I have this:
mItems.add(item);
notifyItemInserted(getItemCount() - 1);
I don't know the details of the notifyItemInserted() call, but it appears to be on a separate thread, which means that smoothScrollToPosition() is called before the views have been laid out after the insertion. Hence, it only scrolls to the second last item.
I have tried looking for a "callback" function along the lines of onItemInserted but I did not have any luck. eg, no answer Here.
How do I solve this problem?
EDIT START
I've simplified the code in a new project in hope to find the problem, and found out what the problem is. It appears to be a problem caused by CoordinatorLayout/AppBarLayout when scrolling flag is enabled. It seems as though the scrolling did not take into consideration the extra scrolling space added by the AppBarLayout.
In the sample codes below, if you disable the scrolling flag for the app bar, scrolling to the bottom of the screen works perfectly as intended. However, if you enable the AppBarLayout scrolling behavior, and change its height, you'll notice that scrolling to the bottom is off by the given height.
I need the scrolling behavior, so how do I make them play nicely with each other? Please note that I've changed the question to reflect the problem.
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static final int ITEMS_COUNT = 50;
private FloatingActionButton mFloatingActionButton;
private RecyclerView mRecyclerView;
private RecyclerAdapter mRecyclerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFloatingActionButton = (FloatingActionButton) findViewById(R.id.fabButton);
mFloatingActionButton.setOnClickListener(this);
setupRecyclerView();
}
private void setupRecyclerView() {
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerAdapter = new RecyclerAdapter(createItemList());
mRecyclerView.setAdapter(mRecyclerAdapter);
}
private List<String> createItemList() {
List<String> itemList = new ArrayList<>();
for (int i = 0; i < ITEMS_COUNT; i++) {
itemList.add("Item " + i);
}
return itemList;
}
#Override
public void onClick(View v) {
mRecyclerView.scrollToPosition(49);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- changing the height affects the scrolling distance -->
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="Header"
app:layout_scrollFlags="scroll|enterAlways"/> <!-- this is the problem -->
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fabButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="20dp"/>
</android.support.design.widget.CoordinatorLayout>
RecyclerAdapter.java
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<String> mItemList;
public RecyclerAdapter(List<String> itemList) {
mItemList = itemList;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
View view = LayoutInflater.from(context).inflate(R.layout.recycler_item, parent, false);
return RecyclerItemViewHolder.newInstance(view);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
RecyclerItemViewHolder holder = (RecyclerItemViewHolder) viewHolder;
String itemText = mItemList.get(position);
holder.setItemText(itemText);
}
#Override
public int getItemCount() {
return mItemList == null ? 0 : mItemList.size();
}
}
recycler_item.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="8dp"
card_view:cardCornerRadius="4dp">
<TextView
android:id="#+id/itemTextView"
android:layout_width="match_parent"
android:layout_height="?attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:padding="8dp"
style="#style/Base.TextAppearance.AppCompat.Body2"/>
</android.support.v7.widget.CardView>
EDIT END
Doing a bit more research I found this question/answer which has a workaround to this problem. Although not ideal, it will have to do for now. Though the real solution shouldn't have to collapse the AppBarLayout, the scrolling should take into consideration the extra scrolling space needed. Perhaps this is just a bug that is overlooked.
In your addItem() method change this
notifyItemInserted(getItemCount() - 1);
to
notifyItemInserted(mItems.size() - 1);
This will solve the problem!
add this after adding item
notifyItemRangeChanged(0, items.size());
Have you tried
mRecyclerView.smoothScrollToPosition(mRecyclerView.getAdapter().getItemCount());
You can also put it in a runnable like this to make sure item has added before you scroll to it.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mRecyclerView.smoothScrollToPosition(mRecyclerView.getAdapter().getItemCount());
}
}, 1000);
Before you add list to adapter in Recycleview do some sorting by using Collection method according to your need,use this code may help you
Comparator<Long> comparator = Collections.reverseOrder();
Collections.sort(arrayList, comparator);

How to reduce space between items of RecyclerView in Android?

I have implemented Horizontal RecyclerView for Images. Horizontal navigation work fine but unwanted space is drawn between two items of RecyclerView.
RecyclerView item layout-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/imgView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/ic_launcher" />
</LinearLayout>
My RecyclerView layout-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
RecyclerView Setup-
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
HlistViewAdapter adapter = new HlistViewAdapter(pArray);
recyclerView.setAdapter(adapter);
recyclerView.setItemAnimator(new DefaultItemAnimator());
My RecyclerView Adapter-
public class HlistViewAdapter extends RecyclerView.Adapter<HlistViewAdapter.ViewHolder>{
ArrayList<String> pathArray;
public HlistViewAdapter(ArrayList<String> pathArray){
this.pathArray = pathArray;
}
#Override
public HlistViewAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemLayoutView = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.hlist_item_layout, null);
// create ViewHolder
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
#Override
public void onBindViewHolder(HlistViewAdapter.ViewHolder viewHolder, int i) {
viewHolder.imgViewIcon.setImageBitmap(BitmapFactory.decodeFile(pathArray.get(i)));
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ImageView imgViewIcon;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.imgView);
}
}
#Override
public int getItemCount() {
return pathArray.size();
}
}
edited answer after chat with user
the problem was the size of the images being too different to the different android devices, and the impossibility to stretch them to prevent the empty spaces. given that, i recommend the use of a ViewPager instead of a RecyclerView, having that it will provide the same functionality buth with a better controll on how the imageView will react with different sized images.
http://codetheory.in/android-image-slideshow-using-viewpager-pageradapter/

Display UI like facebook messenger in Android java programatically

Image
--
I want to achieve something like this in above image
I have to loop through this json array to get all my datas;
the data contained in my json array are for example
{
'img' : http:\\.....
'name' : XYZ
'msg' : xyz
'time' : abc
}
//this is where I am tring to append everything
final LinearLayout rl = (LinearLayout)main.findViewById(R.id.mainL);
for (int i = 0; i < json.length(); i++) {
try {
JSONObject c = json.getJSONObject(i);
//here components must be created and added to view
}catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I just want to know the how do you programmatically style the views(textview,imageview etc) like in the above image.
Any Help will be appreciated
Ok, the image you are looking at is actually a ListView serving custom-made views.
How does that work?
You will need to subclass the BaseAdapter class. This subclass will contain the underlying data which in your case you are getting as a JSON-formatted reply from the web-server.
When the getView() of the BaseAdapter subclass is called, you can inflate a layout that contains an ImageView and TextViews to display the data onscreen.
The answer is just for future visitors, since the question was asked long day ago. At first, I will just redirect you to my GitHub page where I used RecyclerView to show data and Retrofit to call data. I used Volley also. Finally, let me show simple way to load data to recyclerview.
You need an extra class call it CustomAdapter.
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyViewHolder> {
Context context;
private String countryList[];
private int imgList[];
//constructor
public CustomAdapter(Context context, String countryList[],int imgList[]) {
this.context = context;
this.countryList = countryList;
this.imgList=imgList;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
// inflate the item Layout
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.items, parent, false);
// set the view's size, margins, paddings and layout parameters
MyViewHolder vh = new MyViewHolder(view); // pass the view to View Holder
return vh;
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder myHolder, final int position) {
myHolder.txtName.setText(countryList[position]);
myHolder.imgCountry.setImageResource(imgList[position]);
// implement setOnClickListener event on item view.
myHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// display a toast with person name on item click
Toast.makeText(context, countryList[position], Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return countryList.length;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView txtName;
ImageView imgCountry;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
// get the reference of item view's
txtName = itemView.findViewById(R.id.txt_name);
imgCountry = itemView.findViewById(R.id.img_flag);
}
}
}
And in the MainActivity, you have declare a LayoutManager for RecyclerView and have to call CustomAdapter to load data in RecyclerView.
String countryList[]={"Bangladesh","India","China","Australia","America","New Zealand","Portugal"};
int imgList[]={R.drawable.bd,R.drawable.india,R.drawable.china,R.drawable.australia,R.drawable.america,R.drawable.new_zealand,R.drawable.portugle};
RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// get the reference of RecyclerView
recyclerView = findViewById(R.id.recycler_view);
// set a LinearLayoutManager with default vertical orientation
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
// set a LinearLayoutManager with default Horizontal orientation
// LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.HORIZONTAL,false);
recyclerView.setLayoutManager(linearLayoutManager);
// call the constructor of CustomAdapter to send the reference and data to Adapter
CustomAdapter customAdapter = new CustomAdapter(MainActivity.this,countryList, imgList);
recyclerView.setAdapter(customAdapter); // set the Adapter to RecyclerView
}
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
items.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/img_flag"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_margin="5dp"
app:srcCompat="#mipmap/ic_launcher" />
<TextView
android:id="#+id/txt_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center|left"
android:paddingLeft="10dp"
android:text="TextView"
android:textSize="24sp" />
</LinearLayout>
</LinearLayout>
Here's the github repository. If you are calling data from server then visit my Volley repo.

Categories

Resources