Display UI like facebook messenger in Android java programatically - android

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.

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. (:

LinearLayout in a RecyclerView doesn't scroll

Here is what I am trying to do:
What is the simplest way to create rows that scroll together and are composed of variable sized clickable Views with the same height on Android
Basically create variable width columns that have the same width in every row. Also need to add, delete and add listeners. Seems like a fairly simple task, but I am finding Android's GUI library a lot harder to figure out than Java's and WPF's GUI library.
Here is my RecyclerView:
public class MainActivity extends AppCompatActivity {
private RecyclerView ampRecyclerView;
private RecyclerView.Adapter ampAdapter;
private RecyclerView.LayoutManager ampLayoutManager;
List<FunctionView> myDataset = new ArrayList<FunctionView>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUpRecyclerView();
}
private void setUpRecyclerView() {
LinearLayout linearLayout = findViewById(R.id.main_ll);
linearLayout.setWillNotDraw(false);
ampRecyclerView = (RecyclerView) findViewById(R.id.AmpRecyclerView);
// use a linear layout manager
ampLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
ampRecyclerView.setLayoutManager(ampLayoutManager);
myDataset.add(new FunctionView(this));
myDataset.add(new FunctionView(this));
myDataset.add(new FunctionView(this));
// specify an adapter
ampAdapter = new MainActivityAdapter(myDataset, 1);
ampRecyclerView.setAdapter(ampAdapter);
}
}
My adapter
class MainActivityAdapter extends RecyclerView.Adapter<MainActivityAdapter.FunctionViewHolder> {
private List<FunctionView> views = new ArrayList<FunctionView>();
private List<LinearLayout> llViews = new ArrayList<>();
private int rows;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class FunctionViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public LinearLayout linearLayout;
public FunctionViewHolder(LinearLayout v) {
super(v);
linearLayout = v;
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MainActivityAdapter(List<FunctionView> myDataset, int rows) {
views = myDataset;
this.rows = rows;
}
// Create new views (invoked by the layout manager)
#Override
public MainActivityAdapter.FunctionViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
LinearLayout linearLayout = (LinearLayout) LayoutInflater.from(parent.getContext())
.inflate(R.layout.function_holder, parent, false);
llViews.add(linearLayout);
MainActivityAdapter.FunctionViewHolder vh = new MainActivityAdapter.FunctionViewHolder(linearLayout);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(MainActivityAdapter.FunctionViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
int width = 0;
for(FunctionView fv : views){
holder.linearLayout.addView(fv);
width += fv.getWidth();
}
holder.linearLayout.setMinimumWidth(width);
//TODO set the data
// holder.functionView = views.get(position);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return rows;
}
I know there are glaring design flaws. I am trying to get the scrolling working first, because every layout I try doesn't work how I'd like.
Here is the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_ll"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/AmpRecyclerView"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
and the holder:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
android:isScrollContainer="true"
android:nestedScrollingEnabled="true"
>
</LinearLayout>
as you said there are glaring design flaws, but you need to change the android:layout_height to wrap_content and android:layout_width to match_Parent.
if your item's hight is match_parent then your inner layout's hight becomes the recyclerview's hight then there is no room for other items so there will be no scrolling.
also, put something like a textView in it to be able to see the items.
another note, the name is supposed to be item not holder. holder is related to ViewHolder which is a totally different thing. you can name it according to your activity for example if Your activity name is MainActivity so your activity layout is activity_main, then you can call the inner layouts item_main
I recommend watching a tutorial on youtube or read an article from medium or anywhere (you can simply just google android recyclerview example) to learn the basics.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="#+id/txt_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SAMPLE"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:textSize="30sp"
/>
</LinearLayout>

Layout view does not wrap content after scrolling

I am using a recycler view to show some data. When the app is launched it looks correct as follows with wrap content for height. After I scroll past the last item, I am able to keep scrolling and the data is no longer wrapped, looking like match parent instead for height. Scrolling back up, everything has changed to match parent for the height.
Using past references here, I have tried with ConstraintLayouts and switched height wrapping between the parent layout and the recyclerview itself. Both doesn't help. I am guessing this has to do more with the xml. Please advice.
This is what I expect to always get. This is what I current get when app launches, but changes after I scroll to last item.
When I scroll to last item this happens.
Now if I scroll back up, the height is no longer wrapped. Everything seems to have changed to match parent.
This is xml for the custom view I am using to inflate.
<?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:id="#+id/feed_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/feed_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:paddingRight="10dp"
android:textSize="18sp"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="0dp"
tools:text="Test Title" />
<TextView
android:id="#+id/feed_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textSize="12sp"
app:layout_constraintTop_toBottomOf="#+id/feed_title"
tools:layout_editor_absoluteX="0dp"
android:layout_below="#+id/feed_title"
tools:text="This is some random description for testing purposes. Other wise just typing on to create more stuff..." />
</RelativeLayout>
This is layout for the Recycler View which is placed on a Fragment activity.
<?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="wrap_content"
tools:context=".fragment.CurrentFeedFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/current_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
This is over at my FragmentActivity where I am loading the data for the RecyclerView.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_current_feed, container, false);
initiateTestData();
loadDataToRecyclerView(view);
return view;
}
private void initiateTestData(){
testTitles = new ArrayList<>();
testDescriptions = new ArrayList<>();
for (int i = 5; i < 25; i++) {
testTitles.add("title " + i);
testDescriptions.add("This is some random description for testing purposes. Other wise just typing on to create more stuff... " + i);
Log.d(TAG, "initiateTestData: " + "title " + i);
}
}
private void loadDataToRecyclerView(View v){
Log.d(TAG, "loadDataToRecyclerView: " + testTitles.size());
RecyclerView recyclerView = v.findViewById(R.id.current_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
FeedAdapter adapter = new FeedAdapter(testTitles, testDescriptions, getActivity());
recyclerView.setAdapter(adapter);
recyclerView.setItemAnimator(new DefaultItemAnimator());
}
Don't think this is relevant. But for reference, this is my adapter class.
public class FeedAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private static final String TAG = "FeedAdapter";
private List<String> titles;
private List<String> descriptions;
private Context context;
public FeedAdapter(List<String> titles, List<String> descriptions, Context context) {
this.titles = titles;
this.descriptions = descriptions;
this.context = context;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.custom_current_feed, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder viewHolder, int i) {
final ViewHolder holder = (ViewHolder) viewHolder;
holder.feedTitle.setText(titles.get(i));
holder.feedDescription.setText(descriptions.get(i));
holder.layout.setOnClickListener(v -> {
Log.d(TAG, "Clicked: " + titles.get(i));
Toast.makeText(context, titles.get(i), Toast.LENGTH_SHORT).show();
});
}
#Override
public int getItemCount() {
return titles.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView feedTitle;
TextView feedDescription;
RelativeLayout layout;
public ViewHolder(#NonNull View itemView) {
super(itemView);
feedTitle = itemView.findViewById(R.id.feed_title);
feedDescription = itemView.findViewById(R.id.feed_description);
layout = itemView.findViewById(R.id.feed_layout);
}
}
}
Your recycler view height is wrap_content
And recycler view item height match_parent
I would think you'd want them the other way around.
The RV's height = match_parent, i.e. the recycler view occupies all available height.
The RV item's height = wrap_content, i.e. each item only as tall as it needs to be, so that multiple items can fit.

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
}

Alertdialog inflating RecyclerView android

Im trying to add a view to my Material dialog using setView(...), I want to have my inflated view look like this
That is the recycler view will always take up roughly 2/3 of the screen. That includes when it is empty, where it will be an empty space and when it has many lines of data, where it can become scroll able.
This is my aim. However when I try to inflate this View inside my dialog I get the following..
That screen represents an empty recyclerview taking up most of the screen.
Here is the code
//Adding to dialog
mMaterialDialog = new MaterialDialog(mContext)
.setView(new ISEQDialog(mContext))
//.setBackgroundResource(R.drawable.dublin_watchlist)
.setPositiveButton("OK", new View.OnClickListener() {
#Override
public void onClick(View v) {
mMaterialDialog.dismiss();
}
});
mMaterialDialog.show();
}
});
//View
public class ISEQDialog extends FrameLayout{
SeekBar mBuySeekBar;
TextView mStockHeading;
Context mContext;
View mView;
RecyclerView mStockDataList;
public ISEQDialog(Context context) {
super(context);
this.mContext = context;
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(inflater != null){
mView = inflater.inflate(R.layout.stock_dialog, null);
}
mStockDataList = (RecyclerView) mView.findViewById(R.id.rv_stock_data_list);
//
mStockDataList.setAdapter(new ISEQDialofRecyclerViewAdapter());
LinearLayoutManager layoutManager = new LinearLayoutManager(mContext);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.scrollToPosition(0);
mStockDataList.setLayoutManager(layoutManager);
//mStockDataList.addItemDecoration(new DividerItemDecoration(mContext.getDrawable(R.drawable.divider)));
addView(mView);
}
}
//RecyclerViewAdapter
public class ISEQDialofRecyclerViewAdapter extends RecyclerView.Adapter<ISEQDialofRecyclerViewAdapter.ViewHolder>{
#Override
public ISEQDialofRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
#Override
public void onBindViewHolder(ISEQDialofRecyclerViewAdapter.ViewHolder holder, int position) {
}
#Override
public int getItemCount() {
return 0;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
}
}
//XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv_stock_dialog_heading"
android:layout_weight="0.2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center"
android:textColor="#color/list_divider_pressed"
android:layout_gravity="top"
android:background="#null"
android:textSize="35dp"
android:text="Portfolio Value"
/>
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_stock_data_list"
android:layout_weight="0.7"
android:layout_height="0dp"
android:divider="#drawable/list_selector"
android:dividerHeight="1dip"
android:layout_width="match_parent">
</android.support.v7.widget.RecyclerView>
<SeekBar
android:id="#+id/sb_buy_stocks"
android:layout_weight="0.1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center"
android:indeterminate="false" />
</LinearLayout>
I had the same issue trying to add the recycler view to the dialog.
When i tried troubleshooting i realized that only the constrcutor of the recycler view adapter gets called and stops. The remaining methods as getItemCount(), onCreateViewHolder() and onBindViewHolder() doesn't gets called.
So i did the following
1) i replaced the recyclerview with the linear layout.
2) referenced the linear layout as view holder in code.
3) Then i manually iterated through the list i was to pass to the recycler view and on so i inflated the single row xml file, referenced the views and set text on it.
4) I added the view to the view holder and displayed the dialog. It works
5) This operation inflates the view as we are not recycling anything so if the items to display is below 10-15 you can use this as well or else hits the performance of the app a slight.
In Activity
Dialog myTestDialog = new Dialog(getActivity());
myTestDialog.setContentView(R.layout.order_details_orders_to_deliver);
//get the layout group
ViewGroup layout = (ViewGroup) myTestDialog.findViewById(R.id.order_details_recycler_view);
List<OrderItemDetails> orderItemDetailsList = mDatabaseOperationsAdapter.getOrderDetail(ordersToDeliver.getOrderId());
for (int x = 0; x < orderItemDetailsList.size(); x++) {
OrderItemDetails orderItemDetails = orderItemDetailsList.get(x);
View view = inflater.inflate(R.layout.order_details_row, null);
TextView itemName = (TextView) view.findViewById(R.id.order_details_item_name);
TextView quantity = (TextView) view.findViewById(R.id.order_details_item_quantity);
TextView itemTotal = (TextView) view.findViewById(R.id.order_details_item_total);
itemName.setText(orderItemDetails.getProductName());
quantity.setText(String.valueOf(orderItemDetails.getProductQuantity()));
itemTotal.setText(String.valueOf(orderItemDetails.getTotalPrice()));
layout.addView(view);
}
myTestDialog.show();
Note : order_details_recycler_view is the linear layout not recycler view as i changed it to linear layout keeping the id same.
List orderItemDetailsList is the list that was to be passed to the adapter.
This problem is related to RecyclerView as i know, when it is empty it fills layout, unless you give fixed layout_height.
There is trick, which is you check list of items before you create alertDialog. If empty, create alertDialog without RecyclerView, just with warning text. Otherwise create your custom alertDialog.

Categories

Resources