XML layout doesn't appear in R.layout - java

I am using the androidX CardView.
In order to make a recyclerview adapter for the cards I need to inflate the custom card layout I have made.
Unfortunately the xml of the custom card view doesn't appear in R.layout.(xml_name),while i find normally all the other layouts.
This the code inside the adapter class where I need to inflate:
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
LayoutInflater mInflater = LayoutInflater.from(mContext);
view = mInflater.inflate(R.layout.cardview_item_answer); // not finding this layout
return null;
}
This is the card layout xml (cardview_item_answer.xml) :
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="160dp"
android:layout_height="160dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="5dp"
app:cardCornerRadius="4dp"
>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/image_card"
android:layout_width="match_parent"
android:layout_height="100dp"
android:scaleType="centerCrop"
android:background="#2d2d2d2d">
</androidx.appcompat.widget.AppCompatImageView>
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/text_card"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="test"
android:textSize="13sp"
android:textColor="#color/black"
android:layout_gravity="center"
></androidx.appcompat.widget.AppCompatTextView>
</androidx.appcompat.widget.LinearLayoutCompat>
Do you suggest any ideas ?
Thank you very much !

Solved !
If you ever have this problem -> clean project and invalidate Caches/Restart.

If the XML contains any errors, your build will likely fail - this will cause R.layout to yield unexpected results. I am not seeing a closing tag for the CardView in cardview_item_answer.xml
Try adding a closing tag </androidx.cardview.widget.CardView> at the end of cardview_item_answer.xml

For some reasons neither of the solutions above worked for me.
I just had to use the full path to the layout before being able to use it. In my case the item of a spinner
So I did this:
import com.myProject.R.layout.spinner_item
It is never a suggested autocompletion, at least in my case, in model views. It is in the fragments. Can't make sense of that, but it works in view models too.

Related

RecyclerView animates items all at once instead of one by one

My Problem
I've been trying to get my Recycler View's items to animate as I scroll down. These items are loaded from a local XML and passed through my custom adapter.
I'm using this library for my adapter animation
I noticed that no matter what I tried, the items would just not animate at all, or they would animate all at once (every item would slide in on screen at the same time).
What I've Tried So Far
Utilizing the library I mentioned, I tried animating items in my RecyclerView.Adapter.
> IndexFragment.java snippet
//Create an adapter
SongAdapter adapter = new SongAdapter(songs, getContext());
//Set adapter
AlphaInAnimationAdapter alphaAdapter = new AlphaInAnimationAdapter(adapter);
alphaAdapter.setFirstOnly(false);
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
This one failed somehow. I also tried the setItemAnimator method which also failed.
recyclerView.setItemAnimator(new SlideInLeftAnimator());
Layout Structure
So I assume it has something to do with my RecyclerView being inside of two NestedScrollView's.
Another person seemed to be having a similar issue
Below are some portions of my layout files
activity_main.xml
....
<!-- Fragment Container -->
<android.support.v4.widget.NestedScrollView
android:id="#+id/contentContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
....
This is where I put my fragments
index_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/nestedScrollView"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v4.widget.NestedScrollView>
This is pretty much my Recyclerview and its parent Nested Scrollview.
item_song.xml
<?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">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="1dp">
<!--I have two text views in here. Removed them just for this snippet -->
</LinearLayout>
<!-- This displays a background on each item when I press them AKA touch effects -->
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:clickable="true"
android:background="?android:attr/selectableItemBackground" />
</FrameLayout>
This is the structure of each item in the Recyclerview. I inflate this layout for each item. Pretty straightforward.
Any ideas as to what I could do to solve this issue? Thanks.
So after much testing, I finally came up with a solution that worked.
Change the fragment container in activity_main.xml from NestedScrollView to RelativeLayout or perhaps LinearLayout.
Remove the parent NestedScrollView and keep only the RecyclerView in index_fragment.xml.
Animations now work at last. Yay!
Apparently, it is a bad idea to put your RecyclerView inside of a NestedScrollView.
I read somewhere that because of having to load the proper height of its child layout, the NestedScrollView has to wait for it to completely load, in order to know the total height of the RecyclerView. However, I'm not totally sure if that's the reason, so feel free to correct me.
Hope this helps someone!

ListView headers without list item separators

I'm currently writing an Android app that uses ListView with headers. It works okay, but not really as I want. Every item in ListView has 1-2px separator at the top and bottom of it. So does the header - and that's the problem. It does not look very pretty...
The interesting part is that system apps (like Settings, for instance) does not have such problem.
Here's my example adapter:
setListAdapter(new BaseAdapter() {
#Override
public int getCount() {
return 10;
}
#Override
public Object getItem(int i) {
return i;
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
View v = ((LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(i % 3 == 0 ? R.layout.list_header : android.R.layout.simple_list_item_1, viewGroup, false);
((TextView)v.findViewById(android.R.id.text1)).setText("test");
return v;
}
});
And list header layout file:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello, World"
style="?android:attr/listSeparatorTextViewStyle">
</TextView>
So the question is: how to get rid of the item separators between headers and regular items, just like, for example, Settings app does?
EDIT:
After reading the answers, I want to clear one thing up. I do not want to remove separators completely. I want to remove them only between the header items and regular items. Also, half-measures like "removing separators completely and adding them on some items" do not satisfy me, too.
It seems that you have to use a custom item view for dividers and a little workaround. Let me explain how to manage this:
Do not use the default dividers, remove it.
Create a custom layout with a View at bottom to be the subline for headers.
Create a custom layout with a View at top to have the divider for items.
Then, the two types of dividers will be glue to make only one subline for header part, so dividers should have the same height in order to make a good subline. This will avoid to have a divider above the header sections but keeping the dividers for items list.
Therefore, let me show some code to achieve it. First, don't forget to avoid default divider on the ListView:
<ListView
android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#null"
android:dividerHeight="0dp"/>
Create an item layout with a divider at top set to 1dp (or whatever):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- this is the divider for items -->
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#android:color/darker_gray"/>
<!-- and the rest of item's content in another ViewGroup -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#mipmap/ic_launcher"/>
<TextView
android:id="#+id/item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:textColor="#android:color/white"/>
</LinearLayout>
</LinearLayout>
Finally, the header layout with a divider at bottom (with the same height as item's divider):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/item_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
style="?android:attr/listSeparatorTextViewStyle"/>
<!-- this is the ("half-")divider for header section -->
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#android:color/darker_gray"/>
<!-- this view above will be merged with item's dividers -->
</LinearLayout>
And it gives this result:
Remove the style you have set for the header TextView
Create your own custom style with required divider and set it to TextView
<style name="CustomListSeperatorTextViewStyle" parent="Widget.TextView.ListSeparator">
<item name="android:background">#drawable/your_own_here</item>
Seperator is due to the style you have set with the textview, just remove the style hope this will work.
I just found these parameters that seem to be what you need, you can try adding them in your ListView:
android:headerDividersEnabled="false"
android:footerDividersEnabled="false"
The documentation is available here and indicates:
When set to false, the ListView will not draw the divider after each header view. The default value is true.

How to properly add view programatically?

I know that this topic is nothing new, but I really got stuck with this and tried a lot of answers and still I can't make it clear what and where should I write and use.
I have this layout file settings.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
...
<TextView
android:id="#+id/pass"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="7dp"
android:layout_marginTop="10dp"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/pass_del"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginLeft="7dp"
android:layout_marginTop="7dp"
android:text="Удалить пароль"
android:textAppearance="?android:attr/textAppearanceMedium" />
...
</LinearLayout>
I have TextView passdel that I want to add programmatically. Its onCreate description is passdel=(TextView) findViewById(R.id.pass_del);
And I have these methods
public void onPasSet() {
pass.setText("Сменить пароль");
((LinearLayout)passdel.getParent()).addView(passdel);
}
public void onPasDel() {
pass.setText("Установить пароль");
((LinearLayout)passdel.getParent()).removeView(passdel);
}
onPasDel is working well.
I guess Java takes current layout. So when I remove View, it's on this layout. And when I try to add this View, Java tries to find this view on current layout, but it's removed, so ..nullpointerexception. How should I write all addView stuff properly? How to point on the needed layout?
Why do you need to remove/add this View? If I understood the goal of this component correctly, the best way will be just to hide/show it:
passdel.setVisibility(View.GONE);
passdel.setVisibility(View.VISIBLE);
Of course, after you've removed passdel from ViewGroup, it has no parents anymore, so you'll get NPE while trying to call onPasSet() after onPasDel()
As you suggested, getParent() won't work intil TextView is not instantiated.
You should get Layout in different way.
You can do it by findViewById(R.id.layout.id).
Example:
In XML:
<LinearLayout
...
android:id="#+id/my_layout">
...
In Activity:
LinearLayout ll = (LinearLayout) findViewById(R.id.my_layout);
ll.addView(myView);

Best practice with android fragments?

at the moment I'm calling and building fragments like this:
if (getSupportFragmentManager().findFragmentById(R.id.fragment_list) == null) {
list = new MyListFragment();
getSupportFragmentManager().beginTransaction().add(R.id.fragment_list, list).commit();
}
But I wonder if this is so called best practice, because this seems to me to be much boilerplate code. Are there better ways?
Use XML layouts and Fragment classes. Here I create a layout with 2 fragments. The class inflates the layout fragment_actionbarcompat.xml (that code isn't shown here but it's a basic layout file). And I create a layout file for the activity that houses the 2 fragments.
The ActionBarCompatFragment class overrides the onCreateView method to inflate it's layout. That gets injected into the fragment tag layoutwise.
In your case normally you don't just add in a plain ListFragment, you extend ListFragment and add your custom code into it. It's a way of better supporting fancy patterns like Model-View-Controller. Fragments are meant to be isolated compartments so you can reuse them between activities if you'd like. In most cases your class will hold the logic to load the data that the fragment needs.
ActionBarCompatFragment.java
#Override
public final View onCreateView(LayoutInflater inflater, ViewGroup root, Bundle savedInstanceState) {
final int layoutId = R.layout.fragment_actionbarcompat;
return inflater.inflate(layoutId, root, false);
}
File: activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="#+id/ActionBarCompatFragment"
android:layout_width="#dimen/ActionBarSize"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
class="com.packagename.app.ActionBarCompatFragment" >
<!-- Preview: layout=#layout/fragment_actionbarcompat -->
</fragment>
<fragment
android:id="#+id/ComposerFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_toRightOf="#id/ActionBarCompatFragment"
class="com.packagename.app.ComposerFragment" >
<!-- Preview: layout=#layout/fragment_composer -->
</fragment>
</RelativeLayout>

findViewById crashing when using a custom view with <merge> and <include> tags

I am trying to make a custom view using XML then retrieve its properties and edit them. This custom view is added into the test2 view several times with different id's for each. I have tried to retrieve the id for one of these custom views (player_1) then get the TextView (player_name), and edits its properties and no other views like the player_2 id view.
But I am not sure that this is this even possible? It renders fine, but I get an error every time I try to do this in code. I'm really not sure how to approach this, I can't seem to get inflate to work either to test that instead. Any ideaS?
Thanks!
Game.java
setContentView(R.layout.test2);
View player1 = (View) findViewById(R.id.player_1);
TextView player1Name = (TextView) player1.findViewById(R.id.player_name);
player1Name.setText("John");
test2.xml
<include
layout="#layout/player_view"
android:id="#+id/player_1"
/>
<include
layout="#layout/player_view"
android:id="#+id/player_2"
/>
player_view.xml
<?xml version="1.0" encoding="utf-8"?>
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:player="http://schemas.android.com/apk/res/com.example.android.merge">
<LinearLayout
android:id="#+id/top_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
>
<TextView
android:id="#+id/player_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
>
</TextView>
</LinearLayout>
</merge>
This is a cut down version of player_view.xml, I can post more if needed.
Also I have not worked out if it even prints the error message for this in eclipse, it goes into debug mode and does not explain any further what the issue is.
Your player_view.xml has unknown type, so the include is confused what kind of View is it. Try to do the next:
Use or create new PlayerView class, mergeable with player_view.xml.
Edit test2.xml to:
<PlayerView
android:id="#+id/player_1"
/>
<PlayerView
android:id="#+id/player_2"
/>
then inflate it in your code as following:
setContentView(R.layout.test2);
PlayerView player1 = (PlayerView) findViewById(R.id.player_1);
LayoutInflater inflate = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflate.inflate(R.layout.player_view, player1);
Do the same for player2.

Categories