RecyclerView grid layout manager doesn't center items - android

I inherited some big project with a lot of legacy code and now I'm facing some weird stuff..
I need to make this screen have recyclerview with grid layout manager, 2 columns. This is what I get. Is there a way to center those icons in the middle of the screen? I tried with gravity, but nothing works. Maybe there is some thing inside all that legacy code that is making problem or this is just recyclerView's issue?
This is the item's layout (terrible, don't ask..)
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/color_view_controller_item_background"
android:orientation="vertical">
<TextView
android:id="#+id/textViewSceneKK"
android:layout_width="match_parent"
android:layout_height="#dimen/room_button_height"
android:layout_gravity="center"
android:layout_marginLeft="#dimen/row_filter_text_margin_left"
android:layout_marginRight="#dimen/row_filter_text_margin_left"
android:gravity="center"
android:shadowDx="-1"
android:shadowDy="-1"
android:shadowRadius="1"
android:textSize="#dimen/row_scene_kk_text_size" />
<TextView
android:id="#+id/textViewSceneName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/row_filter_text_margin_bottom"
android:layout_marginLeft="#dimen/row_filter_text_margin_left"
android:layout_marginRight="#dimen/row_filter_text_margin_left"
android:layout_marginTop="#dimen/row_filter_text_margin_top"
android:clickable="false"
android:gravity="center"
android:longClickable="false"
android:textColor="#color/main_text_color"
android:textSize="#dimen/row_browser_right_name_text_size" />
</LinearLayout>
<!--<View-->
<!--android:id="#+id/filterView"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent"-->
<!--android:clickable="false"-->
<!--android:longClickable="false" />-->
<View
android:id="#+id/filterViewClick"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:selectableItemBackground"
android:focusable="false"
android:focusableInTouchMode="false" />
And fragment't layout:
<customview.CustomRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none" />
And the code:
customRecyclerView.setHasFixedSize(false);
customRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
customRecyclerView.addItemDecoration(new DividerItemDecoration(getContext(),
R.drawable.line_separator_empty, DividerItemDecoration.VERTICAL_LIST));
customRecyclerView.setAdapter(adapter);
CustomRecyclerView.java
public class CustomRecyclerView extends RecyclerView {
private boolean enableScroll = true;
public CustomRecyclerView(Context context) {
super(context);
}
public CustomRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public boolean isEnableScroll() {
return enableScroll;
}
public void setEnableScroll(boolean enableScroll) {
this.enableScroll = enableScroll;
}
#Override
public int computeVerticalScrollRange() {
return super.computeVerticalScrollRange();
}
#Override
public boolean onInterceptTouchEvent(MotionEvent e) {
if (enableScroll) {
return super.onInterceptTouchEvent(e);
}
return false;
}
}

You have to use layout gravity to make it center & need to change match-parent to wrap_content, also you have to assign layout gravity runtime. try this code:
Adapter item layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:id="#+id/top_header_rl"
android:background="#color/app_header_color"
android:orientation="vertical">
<TextView
android:id="#+id/textViewSceneKK"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:gravity="center"
android:shadowDx="-1"
android:shadowDy="-1"
android:shadowRadius="1"
android:text="Heder name"
android:textSize="26sp" />
<TextView
android:id="#+id/textViewSceneName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:clickable="false"
android:gravity="center"
android:text="Footer name"
android:longClickable="false"
android:textSize="25sp" />
</LinearLayout>
<!--<View-->
<!--android:id="#+id/filterView"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent"-->
<!--android:clickable="false"-->
<!--android:longClickable="false" />-->
<View
android:id="#+id/filterViewClick"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?android:selectableItemBackground"
android:focusable="false"
android:focusableInTouchMode="false" />
</FrameLayout>
Adapter Code:
public class CenterGridView extends RecyclerView.Adapter<CenterGridView.CenterGridViewViewHolder> {
private Context context;
public CenterGridView(Context context){
this.context =context;
}
#Override
public CenterGridViewViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new CenterGridViewViewHolder(LayoutInflater.from(context).inflate(R.layout.new_tiem,parent,false));
}
#Override
public void onBindViewHolder(CenterGridViewViewHolder holder, int position) {
if(position%2==0){
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.RIGHT;
holder.top_header_rl.setLayoutParams(params);
}else{
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.LEFT;
holder.top_header_rl.setLayoutParams(params);
}
}
#Override
public int getItemCount() {
return 20;
}
class CenterGridViewViewHolder extends RecyclerView.ViewHolder{
private LinearLayout top_header_rl;
public CenterGridViewViewHolder(View itemView) {
super(itemView);
top_header_rl = (LinearLayout)itemView.findViewById(R.id.top_header_rl);
}
}
}
Main Activity 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:gravity="center_horizontal"
android:orientation="vertical">
<com.demostudies.CustomRecyclerView
android:id="#+id/tests"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></com.demostudies.CustomRecyclerView>
</LinearLayout>
// Set Adapter
CustomRecyclerView customRecyclerView = (CustomRecyclerView)findViewById(R.id.tests);
customRecyclerView.setHasFixedSize(false);
customRecyclerView.setLayoutManager(new GridLayoutManager(this, 2));
customRecyclerView.setAdapter(new CenterGridView(this));

try this:
it's working for me
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|center_vertical"
>
</androidx.recyclerview.widget.RecyclerView>

Related

Why Custom ArrayAdapter not showing TextView in a ListView

I have made a custom ArrayAdapter and tried to add the another TextView "Breed" of the animals, but when i execute the program , its not showing the Breed. Where am i doing wrong ? I am scratching my head since long. please help where is the mistake ?
MainActivity.Java
public class MainActivity extends AppCompatActivity {
ListView simpleList;
ArrayList<Item> animalList=new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
simpleList = (ListView) findViewById(R.id.simpleListView);
animalList.add(new Item("Lion",R.drawable.lion,"Khatarnak"));
animalList.add(new Item("Tiger",R.drawable.tiger,"Fudu"));
animalList.add(new Item("Monkey",R.drawable.monkey,"Lallu"));
animalList.add(new Item("Elephant",R.drawable.elephant,"Jabardast"));
animalList.add(new Item("Dog",R.drawable.dog,"ItemDog"));
animalList.add(new Item("Cat",R.drawable.cat,"MeeMee"));
MyAdapter myAdapter=new MyAdapter(this,R.layout.list_view_items,animalList);
simpleList.setAdapter(myAdapter);
}
}
MyAdapter.Java
public class MyAdapter extends ArrayAdapter<Item> {
ArrayList<Item> animalList = new ArrayList<>();
public MyAdapter(Context context, int textViewResourceId, ArrayList<Item> objects) {
super(context, textViewResourceId, objects);
animalList = objects;
}
#Override
public int getCount() {
return super.getCount();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.list_view_items, null);
TextView textView = (TextView) v.findViewById(R.id.textView);
ImageView imageView = (ImageView) v.findViewById(R.id.imageView);
TextView breedView = (TextView)v.findViewById(R.id.breed);
textView.setText(animalList.get(position).getAnimalName());
imageView.setImageResource(animalList.get(position).getAnimalImage());
breedView.setText(animalList.get(position).getBreed());
return v;
}
}
Item.Java
public class Item {
String animalName;
int animalImage;
String breedName;
public String getBreed() {
return breedName;
}
public void setBreed(String breed) {
this.breedName = breedName;
}
public Item(String animalName,int animalImage,String breedName)
{
this.animalImage=animalImage;
this.animalName=animalName;
this.breedName = breedName;
}
public String getAnimalName()
{
return animalName;
}
public int getAnimalImage()
{
return animalImage;
}
}
activity_main.xml
<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"
tools:context=".MainActivity">
<ListView
android:id="#+id/simpleListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="#000"
android:dividerHeight="2dp"/>
</RelativeLayout>
list_view_items.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="horizontal">
<ImageView
android:id="#+id/imageView"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="5dp" />
<TextView
android:id="#+id/textView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Demo"
android:textColor="#000" />
<TextView
android:id="#+id/breed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Breed"
android:textColor="#000" />
</LinearLayout>
This is most likely a problem with the linear layout for each item. The orientation is horizontal, which lays each view one after the other horizontally. The problem is that the text view for the animal type has a width of fill_parent leaving no space for the breed view. If you change it to wrap_content it'll probably work for some of the cases, but might not work with everything.
In any case I think this is a problem with the views' positions and sizes. Try and move them around. Perhaps even a simple change would be placing them vertically:
<?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="horizontal">
<ImageView
android:id="#+id/imageView"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="5dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/textView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Demo"
android:textColor="#000" />
<TextView
android:id="#+id/breed"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Breed"
android:textColor="#000" />
</LinearLayout>
</LinearLayout>
There's perhaps a more efficient way of doing this, but this is just an example. The inner linear layout places one text view on to of the other.
PS: your getCount method is not really doing anything. You can remove it.
replace your layout with my code your issue will resolve.
<?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="horizontal">
<ImageView
android:id="#+id/imageView"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="5dp" />
<TextView
android:id="#+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:text="Demo"
android:textColor="#000" />
<TextView
android:id="#+id/breed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Breed"
android:textColor="#000" />
</LinearLayout>

Movie recyclerview above keyboard in Android

I have my custom BottomSheetDialogFragment.Inside this dialog I have custom edittext and recyclerview.My goal is to move reyclerview above a keyboard,when it' showing. Here is a my custom edittext code
public class WrappedEditText extends android.support.v7.widget.AppCompatEditText {
public WrappedEditText(Context context) {
super(context);
}
public WrappedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WrappedEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Nullable
private View wrapper;
#Nullable
public View getWrapper() {
return wrapper;
}
#Override
public void getFocusedRect(Rect r) {
if (wrapper != null) {
wrapper.getFocusedRect(r);
return;
}
super.getFocusedRect(r);
}
#Override
public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
if (wrapper != null)
return wrapper.getGlobalVisibleRect(r, globalOffset);
return super.getGlobalVisibleRect(r, globalOffset);
}
public void setWrapper(#Nullable View wrapper) {
this.wrapper = wrapper;
}
I'm using this code like this
searchView.setWrapper(rootView);
searchView.setOnFocusChangeListener((view1, b) -> {
if(searchView.getWrapper()==null)
searchView.setWrapper(rootView);
});
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#drawable/slide_menu_background"
android:orientation="vertical">
<RelativeLayout
android:id="#+id/close_view"
android:layout_width="wrap_content"
android:layout_height="#dimen/dimen_p_30"
android:layout_centerHorizontal="true"
android:layout_gravity="center"
android:orientation="vertical">
<View
android:layout_width="#dimen/dimen_p_40"
android:layout_height="#dimen/dimen_p_4"
android:layout_alignParentTop="true"
android:layout_marginTop="#dimen/dimen_p_10"
android:background="#drawable/slide_menu_title_line" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/title_conainer"
android:layout_width="match_parent"
android:layout_height="#dimen/dimen_p_30"
android:layout_below="#+id/close_view">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/dimen_p_30"
android:fontFamily="#font/myriad_geo_medium"
android:text="#string/insert_gif"
android:textColor="#color/black"
android:textSize="#dimen/dimen_p_14" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/search_layout"
android:layout_width="match_parent"
android:layout_height="#dimen/dimen_p_38"
android:layout_below="#+id/title_conainer"
android:layout_marginLeft="#dimen/dimen_p_30"
android:layout_marginRight="#dimen/dimen_p_30"
android:background="#drawable/rounded_corners_white">
<ImageView
android:id="#+id/search_icon"
android:layout_width="#dimen/dimen_p_24"
android:layout_height="#dimen/dimen_p_24"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="#dimen/dimen_p_8"
android:background="#mipmap/search_icon" />
<app.singltone.giphy.WrappedEditText
android:id="#+id/search_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_gravity="center"
android:layout_marginLeft="#dimen/dimen_p_35"
android:layout_marginRight="#dimen/dimen_p_10"
android:background="#null"
android:fontFamily="#font/myriad_geo_medium"
android:gravity="center_vertical"
android:hint="#string/find_gif"
android:imeOptions="actionSearch"
android:inputType="textNoSuggestions"
android:singleLine="true"
android:textColor="#color/black"
android:textColorHint="#59000000"
android:textSize="#dimen/dimen_p_14" />
</RelativeLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/search_layout"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:saveEnabled="true" />
</android.support.v4.widget.NestedScrollView>
</RelativeLayout>
rootView is a main view in xml file.This code working perfect only first time,but when user closed keyboard and then opened it again ,this code does not working.
Is a any way to solve this problem? or is this a correct solution?
Thanks

ViewStub inside custom view returning 'ViewStub must have a valid layoutResource'

I have implemented a custom view like this:
public class HeaderView extends LinearLayout {
#Bind(R.id.bill_summary_layout)
LinearLayout summaryLayout;
#Bind(R.id.bill_balance)
TextView balance;
#Bind(R.id.bill_closedate)
TextView closedDate;
#Bind(R.id.bill_status)
TextView status;
#Bind(R.id.bill_partial_overdue)
ViewStub partialOverdueView;
#Bind(R.id.bill_partial_closed)
ViewStub partialClosedView;
#Bind(R.id.bill_partial_open)
ViewStub partialOpenView;
Bill bill;
public HeaderView(Context context) {
super(context);
initUI(context);
}
public HeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
initUI(context);
}
public HeaderView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initUI(context);
}
private void initUI(Context context) {
LayoutInflater.from(context).inflate(R.layout.header_view, this);
}
public Bill getBill() {
return bill;
}
public void setBill(Bill bill) {
this.bill = bill;
notifyMustRebind();
}
public void notifyMustRebind() {
setupUI();
}
private void setupUI() {
if(this.bill == null)
throw new RuntimeException("O objeto bill tem que estar setado e nao ser nulo. Talvez esqueceu de chamar o setBill?");
switch (bill.getState()) {
case OVERDUE:
setOverdueState();
break;
case OPEN:
setOpenState();
break;
case CLOSED:
setClosedState();
break;
case FUTURE:
setFutureState();
break;
}
}
private void setOverdueState(){
summaryLayout.setBackgroundColor(ContextCompat.getColor(getContext(),R.color.overdue));
LayoutInflater.from(getContext()).inflate(R.layout.partial_overdue_view, this, true);
partialOverdueView.inflate();
}
private void setOpenState(){
summaryLayout.setBackgroundColor(ContextCompat.getColor(getContext(),R.color.open));
partialOpenView.inflate();
}
private void setClosedState(){
summaryLayout.setBackgroundColor(ContextCompat.getColor(getContext(),R.color.closed));
partialClosedView.inflate();
}
private void setFutureState(){
summaryLayout.setBackgroundColor(ContextCompat.getColor(getContext(),R.color.future));
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
ButterKnife.bind(this);
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
ButterKnife.unbind(this);
}
}
The header_view.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="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/bill_summary_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/bg_content_arrow"
android:backgroundTint="#color/colorAccent"
android:orientation="vertical"
android:paddingBottom="#dimen/header_margin"
android:paddingTop="#dimen/header_margin"
>
<TextView
android:id="#+id/bill_balance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingBottom="#dimen/header_text_margin"
android:text="R$ 2.300,10"
android:textColor="#android:color/white"
android:textSize="22sp"
android:textStyle="bold"
/>
<TextView
android:id="#+id/bill_closedate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingBottom="#dimen/header_text_margin"
android:text="Vencimento 15 MAI"
android:textColor="#android:color/white"
android:textSize="18sp"
/>
<TextView
android:id="#+id/bill_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingBottom="#dimen/header_text_margin"
android:text="Fechamento em 5 de Julho"
android:textAllCaps="true"
android:textColor="#android:color/white"
android:textSize="12sp"
/>
</LinearLayout>
<ViewStub
android:id="#+id/bill_partial_overdue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout="#layout/partial_overdue_view"
/>
<ViewStub
android:id="#+id/bill_partial_closed"
layout="#layout/partial_closed_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ViewStub
android:id="#+id/bill_partial_open"
layout="#layout/partial_open_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/colorAccent"/>
</LinearLayout>
The view above is inside another view called bill_view:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<br.com.leonardo2204.nubanktest.ui.custom.HeaderView
android:id="#+id/header_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/list_header_padding">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:paddingLeft="#dimen/list_header_padding"
android:paddingStart="#dimen/list_header_padding"
android:text="De 5 Mar até 5 abr"
android:textAllCaps="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:paddingEnd="#dimen/list_header_padding"
android:paddingRight="#dimen/list_header_padding"
android:text="Valores em R$"
android:textAllCaps="true" />
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
The view above is inflated inside a PagerAdapter, as this:
#Override
public Object instantiateItem(ViewGroup container, int position) {
View v = LayoutInflater.from(container.getContext()).inflate(R.layout.bill_view, container, false);
HeaderView header = (HeaderView) v.findViewById(R.id.header_view);
header.setBill(billList.get(position));
container.addView(v);
return v;
}
The problem is, I'm getting the stack trace below :
Process: br.com.leonardo2204.nubanktest, PID: 10815
java.lang.IllegalArgumentException: ViewStub must have a valid layoutResource
at android.view.ViewStub.inflate(ViewStub.java:289)
at br.com.leonardo2204.nubanktest.ui.custom.HeaderView.setClosedState(HeaderView.java:112)
at br.com.leonardo2204.nubanktest.ui.custom.HeaderView.setupUI(HeaderView.java:91)
at br.com.leonardo2204.nubanktest.ui.custom.HeaderView.notifyMustRebind(HeaderView.java:76)
at br.com.leonardo2204.nubanktest.ui.custom.HeaderView.setBill(HeaderView.java:72)
at br.com.leonardo2204.nubanktest.ui.adapter.ViewPagerAdapter.instantiateItem(ViewPagerAdapter.java:30)
at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:870)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1086)
at android.support.v4.view.ViewPager.populate(ViewPager.java:952)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1474)
at android.view.View.measure(View.java:17547)
What I am doing wrong ? Is there a better approach to inflate the header view other than inside instantiateView ?
Thanks !
USE
android:layout="#layout/xyz"
instead of
layout="#layout/xyz"

Android Cardviews and XML Loading Images Make App Lag

I'm using 4 cardviews in XML, and they are only loading a picture and a textview each. Not using a RecyclerView or anything dynamic.
My Navigation drawer opens with so much lag and the entire app lags after adding the cardviews. Is there a better way to implement these cardviews?
These are simply nested within a Linearlayout.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/app_bar_main"
android:orientation="vertical"
tools:context="com.example.jesse.apbiologystudyappv2.MainActivity">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view_1_natural_selection"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:src="#drawable/apple_tree" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Natural Selection and Evolution"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="#color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view_2_descent_and_ancestry"
android:layout_gravity="center"
android:layout_marginBottom="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:src="#drawable/gravestones" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Descent and Ancestry"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="#color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view_3_speciation"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_marginBottom="16dp"
android:layout_height="wrap_content"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:src="#drawable/dinosaur" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Speciation and Extinction"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="#color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view_4_origin_of_life"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:src="#drawable/bacteria" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Origin of Life"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="#color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
You should use RecyclerView to manage memory as well. To do this you need only one CardView.
activity_main.xml :
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/app_bar_main"
android:orientation="vertical"
tools:context="com.example.jesse.apbiologystudyappv2.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/lstActions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="1dp"
android:padding="0dp"/>
</LinearLayout>
cardview_item.xml:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view_1_natural_selection"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:id="#+id/imgActoun" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/txtActoun"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="#color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
Create a class ActionItem.java like this:
public class ActionItem
{
private final int mTitleResID;
private final int mIconResID;
public ActionItem(int titleResID, int iconResID)
{
this.mTitleResID = titleResID;
this.mIconResID = iconResID;
}
public int getTitleResID()
{
return mTitleResID;
}
public int getIconResID()
{
return mIconResID;
}
}
onCreateView in MainActivity must be like this :
public View onCreateView(String name, Context context, AttributeSet attrs)
{
List<ActionItem> actionItems = new ArrayList<>();
actionItems.add(new ActionItem(R.string.NaturalSelectionAndEvolution, R.drawable.apple_tree));
actionItems.add(new ActionItem(R.string.DescentAndAncestry, R.drawable.gravestones));
RecyclerView lstActions = (RecyclerView) findViewById(R.id.lstActions);
ActionAdapter actionAdapter = new ActionAdapter(actionItems);
lstActions.setAdapter(actionAdapter);
return super.onCreateView(name, context, attrs);
}
Add ActionAdapter Like this:
public class ActionAdapter extends RecyclerView.Adapter<ActionAdapter.ActionHolder>
{
private final List<ActionItem> mActionItems;
public ActionAdapter(List<ActionItem> actionItems)
{
this.mActionItems = actionItems;
}
#Override
public ActionHolder onCreateViewHolder(ViewGroup viewGroup, int i)
{
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
View itemView = inflater.inflate(R.layout.cardview_item, viewGroup, false);
return new ActionHolder(itemView);
}
#Override
public void onBindViewHolder(ActionHolder actionHolder, int position)
{
ActionItem actionItem = mActionItems.get(position);
actionHolder.mTxtTitle.setText(actionItem.getTitleResID());
actionHolder.mImgIcon.setImageResource(actionItem.getIconResID());
}
#Override
public int getItemCount()
{
return this.mActionItems.size();
}
public class ActionHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
protected final TextView mTxtTitle;
protected final ImageView mImgIcon;
public ActionHolder(View view)
{
super(view);
mImgIcon = (ImageView) view.findViewById(R.id.imgAction);
mTxtTitle = (TextView) view.findViewById(R.id.txtAction);
}
}
}
I implemented Fred's answer with a few changes. Instead of putting this
public View onCreateView(String name, Context context, AttributeSet attrs){
List<ActionItem> actionItems = new ArrayList<>();
actionItems.add(new ActionItem(R.string.NaturalSelectionAndEvolution, R.drawable.apple_tree));
actionItems.add(new ActionItem(R.string.DescentAndAncestry, R.drawable.gravestones));
RecyclerView lstActions = (RecyclerView) findViewById(R.id.lstActions);
ActionAdapter actionAdapter = new ActionAdapter(actionItems);
lstActions.setAdapter(actionAdapter);
return super.onCreateView(name, context, attrs);
}
in onCreateView, I implemented it all in onCreate of MainActivity and put some declerations at the top of the class:
private RecyclerView.LayoutManager mLayoutManager;
private List<ActionItem> actionItems = new ArrayList<>();
private RecyclerView listOfCards;
private ActionAdapter actionAdapter;
I was still getting a lot of lag, however, and it was due to XML loading the images. So, I used the Glide dependency available on Github instead. In ActionAdapter, I added a context requirement and then changed onBindViewHolder. The context requirement is there to satisfy Glide's method which requires a context.
public class ActionAdapter extends RecyclerView.Adapter<ActionAdapter.ActionHolder> {
private final List<ActionItem> mActionItems;
private Context mContext;
public ActionAdapter(List<ActionItem> actionItems, Context context) {
this.mActionItems = actionItems;
this.mContext = context;
}
#Override
public ActionHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
View itemView = inflater.inflate(R.layout.cardview_item, viewGroup, false);
return new ActionHolder(itemView);
}
#Override
public void onBindViewHolder(ActionHolder actionHolder, int position) {
ActionItem actionItem = mActionItems.get(position);
actionHolder.mTxtTitle.setText(actionItem.getTitleResID());
Glide.with(mContext).load(actionItem.getIconResID()).into(actionHolder.mImgIcon);
}
#Override
public int getItemCount() {
return this.mActionItems.size();
}
public class ActionHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
protected final TextView mTxtTitle;
protected final ImageView mImgIcon;
public ActionHolder(View view) {
super(view);
mImgIcon = (ImageView) view.findViewById(R.id.imgAction);
mTxtTitle = (TextView) view.findViewById(R.id.txtAction);
}
#Override
public void onClick(View v) {
//do something
}
}
}
As you can see, i removed actionHolder.mImgIcon .setText.... from onBindViewHolder and replaced it with the Glide command. This makes the application skip no frames when launching and produce no more occurences of lag when opening the navigation drawer. Turns out the lag was produced by a combination of redundant RelativeLayouts, XML insertion of the picture (rather than the more efficient glide) and not using a RecyclerView.

xml LinearLayout different behaviours

I am trying to create a custom button layout. I created an xml file "custom_button.xml" which I then inflate in the "ButtonLanguageSelection" class. In this class I added the onClickListener. I added this class to the "main_activity.xml". It behaves like it should except it won't receive any touch events. Then I copied the code from "custom_button.xml" and added it directly without inflating it, I just added the android:onClick parameter and in this way it worked. I can't find out what would be the problem, the layouts are the same.
Has some of you have similar problems? What could be the problem? I attached the code if it helps someone to find the problem.
Thank you for any help!
custom_button.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/button_language_selection_states"
android:weightSum="1"
android:clickable="true"
>
<TextView
android:id="#+id/textview_select_language"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center"
android:gravity="center_horizontal"
android:paddingTop="30px"
android:layout_weight="0.4"
android:textSize="21sp"
android:textColor="#333333"
/>
<View
android:layout_width="match_parent"
android:background="#drawable/gradient"
android:layout_height="1dp"
android:layout_margin="10px">
</View>
<TextView
android:id="#+id/textview_language"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center"
android:paddingTop="40px"
android:layout_weight="0.6"
android:textSize="28sp"
android:textColor="#ffffff"
/>
</LinearLayout>
ButtonLanguageSelection
public class ButtonLanguageSelection extends LinearLayout
{
private TextView introductoryTextView;
private TextView language;
private final String TAG = "ButtonLanguageSelection";
public ButtonLanguageSelection(Context context) {
super(context);
}
public ButtonLanguageSelection(Context context, AttributeSet attrs)
{
super(context, attrs);
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutInflater.inflate(R.layout.button_language_selection, this);
introductoryTextView = (TextView)findViewById(R.id.textview_select_language);
language = (TextView)findViewById(R.id.textview_language);
this.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "onclick");
}
});
}
public ButtonLanguageSelection(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setIntroductoryTextView(String s)
{
introductoryTextView.setText(s);
}
public void setLanguage(String s)
{
language.setText(s);
}
}
main_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/screen_welcome_bg">
<defaultpackage.ButtonLanguageSelection
android:id="#+id/ButtonLanguageSelection_Slovene"
android:layout_width="341px"
android:layout_height="260px"
android:layout_marginRight="2px"/>
<defaultpackage.ButtonLanguageSelection
android:id="#+id/ButtonLanguageSelection_Italian"
android:layout_width="341px"
android:layout_height="260px"
android:layout_marginRight="2px"/>
<!--<defaultpackage.ButtonLanguageSelection-->
<!--android:id="#+id/ButtonLanguageSelection_English"-->
<!--android:layout_width="341px"-->
<!--android:layout_height="260px" />-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="341px"
android:layout_height="260px"
android:background="#drawable/button_language_selection_states"
android:weightSum="1"
android:clickable="true"
android:onClick="sendMessage"
>
<TextView
android:id="#+id/textview_select_language"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center"
android:gravity="center_horizontal"
android:paddingTop="30px"
android:layout_weight="0.4"
android:textSize="21sp"
android:textColor="#333333"
/>
<View
android:layout_width="match_parent"
android:background="#drawable/gradient"
android:layout_height="1dp"
android:layout_margin="10px">
</View>
<TextView
android:id="#+id/textview_language"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center"
android:paddingTop="40px"
android:layout_weight="0.6"
android:textSize="28sp"
android:textColor="#ffffff"
/>
</LinearLayout>
I think the problem is writing all the init code in only one constructor. Consider making an init function and call it from all the constructors. Also consider setting the onClick events listeners in your activity rather than than the layout constructor itself.

Categories

Resources