Inflated layout's children not showing - java

I am using a DraggableGridView from here.
What I did before was add a simple programmatically built ImageViews to the grid. That works perfectly fine.
I am now trying to add a Layout instead. I tried RelativeLayout, Framelayout, FrameLayout inside of a RelativeLayout.
Here is my code as of now:
/**
* Rebuild the grid view, e.g. after the adapter has been filled or a backup is restored
*/
private void renewGrid()
{
dgv.removeAllViews();
for(int i = 0; i < adapter.getCount(); i++)
{
LayoutInflater inflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
dgv = (DraggableGridView) inflater.inflate(R.layout.grid_item_layout, dgv);
FrameLayout fl = (FrameLayout) dgv.findViewById(R.id.grid_images);
ImageView icon = (ImageView) fl.findViewById(R.id.qstile);
icon.setImageDrawable(res.getDrawable(res.getIdentifier("qstile_" + adapter.getItem(i), "drawable", packagename)));
}
}
Following the grid_item_layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal" >
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/grid_images">
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:src="#drawable/icon_delete"/>
<ImageView
android:id="#+id/qstile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout>
<TextView
android:id="#+id/invisible_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text=""
android:visibility="gone" />
</RelativeLayout>
The RelativeLayout gets inflated into the grid nicely. I can observe this via DDMS and the "Dump view hierachy" function. The tree shows all RelativeLayouts inside the grid, but each of it doesn't have any children.
BUT... That is not true. If I step through the code and observe the inflated layouts I can see the children. So they are set up, get added just like told in the XML, but don't get drawn.
The OnItemClick listener on the children of the grid also works...
Any hint about what I'm missing here? I already tried several ways, even creating the complete layout programmatically and then adding it to the grid as children. Still no luck. None of the children get added.
Is that maybe an issue with the used DraggableGridView?

After searching for another few hours I found a fix in this SO thread
Basically I now extend DraggableGridView from FrameLayout rather than ViewGroup. This hasn't had any noticeable side effects to me.

Related

Android - FirebaseListAdapter duplicating runtime layout changes

i'm here to ask if anyone knows a workaround to the issue i'm failing to fix.
Basically i'm coding a simple Chat App in Android using Firebase as an exercise. I'm using a ListView in my main layout and a simple Layout to use for each "message bubble". Here comes the problem: when i visualize the messages that i retrieve from Firebase i change the color of the bubble based on the current user in runtime, when first loaded each bubble has the right color, but by scrolling up and down my messages more and more bubbles take on the "ActiveUser" color even if they belong to different users, any ideas? I'll leave the code i'm using down below
Main Layout ListView
<ListView
android:id="#+id/list_of_messages"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/inputArea"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:divider="#android:color/transparent"
android:dividerHeight="16dp"
android:paddingStart="15dp"
android:paddingBottom="5dp"
android:paddingEnd="15dp"
android:paddingTop="10dp"/>
Message Bubble Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:id="#+id/message_bubble"
android:background="#drawable/normal_message_background">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:id="#+id/message_user"
android:textStyle="normal|bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="#id/message_user"
android:layout_marginStart="10dp"
android:id="#+id/message_time" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/message_user"
android:layout_alignParentStart="true"
android:layout_marginTop="5dp"
android:id="#+id/message_text"
android:textAppearance="#style/TextAppearance.AppCompat.Body1"
android:textSize="18sp" />
FirebaseListAdapter and runtime style change code chunk
private void displayChatMessages() {
ListView listOfMessages = findViewById(R.id.list_of_messages);
FirebaseListOptions<ChatMessage> options = new FirebaseListOptions.Builder<ChatMessage>().setLayout(R.layout.message)
.setQuery(dbMessagesReference, ChatMessage.class).build();
mAdapter = new FirebaseListAdapter<ChatMessage>(options) {
#Override
protected void populateView(View v, ChatMessage model, int position) {
// Get references to the views of message.xml
RelativeLayout messageBubble = v.findViewById(R.id.message_bubble);
TextView messageText = v.findViewById(R.id.message_text);
TextView messageUser = v.findViewById(R.id.message_user);
TextView messageTime = v.findViewById(R.id.message_time);
// Set their text
messageText.setText(model.getMessageText());
messageUser.setText(model.getMessageUser());
messageTime.setText(model.getMessageTime());
if (messageUser.getText().equals(FirebaseAuth.getInstance().getCurrentUser().getDisplayName()))
messageBubble.setBackgroundResource(R.drawable.active_user_message_background);
}
};
listOfMessages.setAdapter(mAdapter);
}
EDIT:
I've fixed the problem by declaring the else statement to set the normal drawable variant back if the usernames did not match, however once changed the background Resource in runtime the bubble looks smaller and doesn't wrap around all the text, does anyone know the reason of this?
2ND EDIT:
I've found the solution to my second problem in this other post: Where'd padding go, when setting background Drawable?
Apparently the issue should have been fixed back in API 19/21, however if you still experience that problem apply the workaround explained in the thread linked above
ListView will reuse views to help with performance. This means when we scroll the adapter will just place your content in a view that was slated to go off screen rather than inflating a new view. This is causing all views that you set the current user background on to always keep that background since you don't have a condition to set it back if the view is filled with non-current user data.
To fix this add the following condition:
if (messageUser.getText().equals(FirebaseAuth.getInstance().getCurrentUser().getDisplayName())){
messageBubble.setBackgroundResource(R.drawable.active_user_message_background);
}
else{
messageBubble.setBackgroundResource(R.drawable.normal_message_background);
}

there is some way to make my own item in xml?

i work on android-studio project, and my question is about if
there is some way i can define in xml type of some item that contain
few edit text and buttons, and open listview that contain the item i create?
somthing like :
<item
<Editext(some setting)/>
<Edittext 1(some setting)/>
<Button(some setting)/>
/>
and then some adapter that adjust or something like that, that i can add to ListView.
i saw in youtube some videos that try to explain that but i get stock.. i dno't really get this.
This took my a while to figure out, but it works.
Create your Layout file just however you want. Save it as res/layout/something.txt. Example:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:text="hello"
android:layout_height="wrap_content"
android:layout_width="150dp"
android:id="#+id/text1"/>
<TextView
android:text="world"
android:layout_height="wrap_content"
android:layout_width="150dp"
android:id="#+id/text2"/>
</LinearLayout>
Use it in your code as follows:
LinearLayout mainLinearLayout = new LinearLayout(getApplicationContext());
// inflate your container
View view = inflater.inflate(R.layout.something, null);
// you can make changes to the elements like this:
TextView txt1 = (TextView) view.findViewById(R.id.text1);
TextView txt2 = (TextView) view.findViewById(R.id.text2);
view.setTag(tag);
// add to main layout
mainLinearLayout.addView(view);
Where tag is an unique integer to identify the View. You don't need to set the tag if you're using the container only once.
I didn't use an Adapter when I made this. I just used a ScrollView to make a continous list of entries. Change this to your needs.

Overlaying slider element on top of CardView

I am trying to build a slider that slides on top of my current view in Android. I built the slider using the SlideUp library found here https://github.com/mancj/SlideUp-Android. The slider is taking the inner RelativeLayout as a view source. When I pull up the slider it ends up behind the CardView. I've looked through all the methods in the library and there isn't one that allows you to move the slider to the foreground. I've also tried to bring the slider view to foreground with .bringToFront() method. Moving the slider view before the CardView in the .xml file does nothing either. Is there a good way to bring the slider to foreground... or the CardView in the background? (without hiding the CardView)
JAVA
//code to build slider
View slideView = findViewById(R.id.slider);
//tried putting slideView.bringToFront() here before passing it to the object but that did nothing
SlideUp slideUp = new SlideUpBuilder(slideView)
.withStartState(SlideUp.State.HIDDEN)
.withStartGravity(Gravity.BOTTOM)
.build();
//code to bring up slider. View "share" exists, it's just irrelevant so I didn't include in the .xml file
buttonView.findViewById(R.id.share).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//tried putting slideView.bringToFront() here as well
slideUp.toggle(); //toggles slider up/down
}
});
XML
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:background="#color/background"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginRight="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="60dp">
</android.support.v7.widget.CardView>
<RelativeLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/slider"
android:background="#color/primary">
</RelativeLayout>
</RelativeLayout>
I figured it out. I found out I can add android:elevation="2dp" for the slider and 0dp for the CardView

Android way to add new xml layout

I have an activity with a layout. After a GET request to a server, I want to dynamically add new elements to that layout.
I want to add those elements multiple times, using a for-structure.
The elements I want to add are the following:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="64dp"
android:background="#drawable/outer_border"
android:padding="2dp"
android:layout_marginTop="20dp">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:background="#color/orange"
android:height="40dp"
android:paddingLeft="5dp"
android:paddingTop="5dp"
android:text="TW"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#ffffff"
android:textSize="70px"
android:width="60dp" />
<CheckBox
android:id="#+id/checkBox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/textView3"
android:layout_toLeftOf="#+id/checkBox1"
android:text="inca 6 zile"
android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
I've tried this:
for(int i = 0; i < homeworkList.size(); i++){
LinearLayout linearLayout = (LinearLayout) currentActivity.findViewById(R.id.linearLayout2);
RelativeLayout newLayout = new RelativeLayout(currentActivity, null, R.style.HomeworkLayout);
TextView text = new TextView(currentActivity);
TextView text1 = new TextView(currentActivity);
text1.setText("da");
text.setText("nu");
newLayout.addView(text1);
newLayout.addView(text);
linearLayout.addView(newLayout, relativeParams);
}
But no result, those textview were added but on top of each other, and the relative layout I just added in that for doesn't have any of the style I added using R.style.HomeworkLayout.
What is the best way to add the elements with so much styling? Why isn't this working?
those textview were added but on top of each other
That's what you told RelativeLayout to do. If you wanted to specify positioning rules, you would have passed instances of RelativeLayout.LayoutParams to addView() when you were adding the TextView widgets.
What is the best way to add the elements with so much styling?
Well, probably, the answer is to use ListView or RecyclerView. That being said, the simplest solution that keeps your vertical LinearLayout would be to inflate the rows:
LinearLayout linearLayout = (LinearLayout) currentActivity.findViewById(R.id.linearLayout2);
for(int i = 0; i < homeworkList.size(); i++){
View row=getLayoutInflater().inflate(R.layout.row, linearLayout, false);
// call findViewById() to retrieve your TextView widgets and fill them in
linearLayout.addView(row);
}
This assumes that the layout you show in your question is named R.layout.row; adjust the inflate() call as needed if that is not the name. This also assumes that the code snippet is in a method on the activity that is hosting this UI.
If you want to use a layout which is repeating why don't you prefer using a custom liner layout.
A simple and basic solution is mentioned on this link
http://android-coding-tuts.blogspot.in/2012/02/custom-listview-with-sliding-view-for.html
You should look up Fragments for this. They have a separate control-view structure and you can just create a new fragment for each subview.
Check it out here:
http://developer.android.com/guide/components/fragments.html

Dynamically including an XML relative layout multiple times in a parent view

I have an XML RelativeLayout snippet that I would like to include several times (from a loop) in my main View. The problem seems to be -- is there a way to avoid hard-coding the parent of the RatingBar, since each time I include the RelativeLayout snippet my elements will need to have different ids?
As far as I can tell, the recommended way is to get the layout snippet and then override the android:id for each element to be unique, and then override the android:layout_below manually for each element that has relative positioning. This seems a little kludgy -- is there any way to have these bindings get done automatically?
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:id="#+id/relativeView">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:text="Label"
android:textAppearance="?android:attr/textAppearanceMedium" />
<RatingBar
android:id="#+id/ratingBar1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/textView1" />
</RelativeLayout>
you just need to change the id of the RelativeLayout
like
int BASEID=200;
View v = mLayoutInflator.inflate(R.layout.myRelativeLayout, null);
for (int i;i<10;i++){
v.findViewById(R.id.relativeView).setId(i+BASEID);
}
mRootView.addView(v,...);
then when you need to get the RatingBar for suppose the 4th RelativeLayout you added you can call
RatingBar mRatingBar = (RatingBar)mRootView.findViewById(BASEID+3).findViewById(R.id.ratingBar1);

Categories

Resources