Is it possible to somehow take an array, for example, a TextView, which are in the current Activity, or is it necessary to take each view?
You can get all the views of your xml programmatically as below:
bind your ViewGroup / Parent layout
Then the child View are accessible in if condition
val container = findViewById(R.id.container) as ViewGroup
for (i in 0 until container.childCount) {
val v = container.getChildAt(i)
if (v is Button) {
// You will get Button here
}
else if(v is TextView){
// You will get textView here
}
}
Related
I have a rank of players in a viewgroup displayed programmatically.
A player has a class and a method to show it inside the viewgroup:
public void show(Activity a, ViewGroup container)
{
LayoutInflater inflater = (LayoutInflater) a.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
int res = position == 1 ? R.layout.ins_rank_first : R.layout.ins_rank;
View view = inflater.inflate(res, container, false);
CircleImageView imgUser = view.findViewById(R.id.img_rank_user);
TextView txtUser = view.findViewById(R.id.txt_rank_user);
TextView txtPosition = view.findViewById(R.id.txt_rank_position);
TextView txtScore = view.findViewById(R.id.txt_rank_score);
//load image inside imageview
a.loadImage(userImage, imgUser, R.drawable.ic_profile);
if(position == 2)
imgUser.setBorderColor(a.getResources().getColor(R.color.silver));
else if(position == 3)
imgUser.setBorderColor(a.getResources().getColor(R.color.bronze));
txtUser.setText(username);
txtPosition.setText(String.valueOf(position));
txtScore.setText(String.valueOf(score));
container.addView(view);
}
So I want to ask the server every 5 seconds to generate a new ranking to make it real-time, but I don't want to remove all ViewGroup's views because the list could be long. Therefor I would like to compare new ranking positions to older ones and then exchange views when needed. How could I achieve this?
I know that there are similar questions, but i couldn't really understand, so i decided to ask again.
I am trying to do something similar to a chat, so in the list view there would be 2 types of rows, the ones of the received items and the ones of the sent items. The ones that were received will inflate the recvRow.xml layout, and the ones that were sent will inflate the sentRow.xml layout.
I have a list of items that are suposed to be shown ( name, img, etc) and i have a boolean that represents if the object was sent or received.
The problem is that those layouts have different buttons and if for example i receive something first, it will obviously load the recvRow.xml , but then if I try to send something, it will throw a nullpointerexception because on one of the buttons that only exists in the sentRow.xml layout (and doesn't exist in the recvRow.xml).
Since i am checking that boolean that i told you guys before, i don't see the need to use the getItemViewType method.
Here is my code for the getView method:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
viewHolder = null;
if (convertView == null) {
viewHolder=new ViewHolder();
LayoutInflater layoutInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
System.out.println("Transf Rec Adapter : Going to draw AN ITEM : "+ listOfItems.get(position).getAppName());
System.out.println("Transf Rec Adapter : The received bool is : "+ listOfItems.get(position).isReceived());
if(listOfItems.get(position).isReceived()){
view=layoutInflater.inflate(R.layout.highway_transf_record_recv_row,parent,false);
viewHolder.deleteFile=(ImageView) view.findViewById(R.id.transfRecRowDelete);
viewHolder.installButton = (ImageView) view.findViewById(R.id.transfRecRowInstall);
}else{//se enviado
view=layoutInflater.inflate(R.layout.highway_transf_record_sent_row,parent,false);
viewHolder.reSendButton=(ImageView) view.findViewById(R.id.transfRecReSendButton);
}
viewHolder.appImageIcon=(ImageView) view.findViewById(R.id.transfRecRowImage);
viewHolder.appNameLabel=(TextView) view.findViewById(R.id.transfRecRowText);
viewHolder.appVersionLabel = (TextView) view.findViewById(R.id.transfRecRowAppVersion);
viewHolder.senderInfo = (TextView) view.findViewById(R.id.apkOrigin);
viewHolder.rowImageLayout = (RelativeLayout) view.findViewById(R.id.transfRecRowImageLayout);
viewHolder.appInfoLayout = (RelativeLayout) view.findViewById(R.id.appInfoLayout);
}else{
view= convertView;
viewHolder = (ViewHolder) convertView.getTag();
}
if(listOfItems.get(position).isReceived()){
System.out.println("INSIDE THE GET VIEW TRANSF REC ADAPTER : RECEIVED SOMETHING");
viewHolder.senderInfo.setText("You received this app :");
myOnClickListenerToInstall = new MyOnClickListenerToInstall(position);
viewHolder.installButton.setOnClickListener(myOnClickListenerToInstall);
myOnClickListenerToDelete= new MyOnClickListenerToDelete(position);
viewHolder.deleteFile.setOnClickListener(myOnClickListenerToDelete);
}else{
System.out.println("INSIDE THE GET VIEW TRANSF REC ADAPTER : SENT SOMETHING");
viewHolder.senderInfo.setText("You sent this app :");
ReSendListener reSendListener=new ReSendListener(position);
viewHolder.reSendButton.setOnClickListener(reSendListener);//null pointer exception here
}
viewHolder.appNameLabel.setText(listOfItems.get(position).getAppName());
viewHolder.appImageIcon.setImageDrawable(listOfItems.get(position).getIcon());
viewHolder.appVersionLabel.setText(listOfItems.get(position).getVersionName());
view.setTag(viewHolder);
return view;
}
The id's are right and everything exists on the viewHolder.
You need to use getItemViewType because of recycling. Otherwise you can try to recycle a received item into a non-received view, which will screw things up royally. However it is ok for getItemViewType to just return 0 or 1 based on that boolean. It doesn't need to be very complicated for 2 view types.
You should override getItemViewType() in your adapter. This method will indicate the type of view which should be inflated for each row. You also need to override getViewTypeCount().
I'm trying to make my first Android application, and I want to drag and drop coins into boxes. The onDrag method I found was this:
#Override
public boolean onDrag(View v, DragEvent e) { // onDrag(waarnaartoe, event)
if (e.getAction()==DragEvent.ACTION_DROP) {
// user interface
View view = (View) e.getLocalState();
ViewGroup from = (ViewGroup) view.getParent();
from.removeView(view);
FrameLayout to = (FrameLayout) v;
to.addView(view);
view.setVisibility(View.VISIBLE);
}
return true;
}
The boxes are LinearLayouts, so I changed the original code i.e.
from
ViewGroup from = (ViewGroup) view.getParent(); (which works fine)
to
LinearLayout from = (LinearLayout) view.getParent();
However, the app crashes if I try to drop something onto a box. The reason I want to get the LinearLayout is that I made a Map which connects LinearLayouts to "boxes" (which are theoretical objects with certain properties).
Could anyone explain to me why I cannot replace ViewGroup by LinearLayout?
The function which I copied was not applicable to my program. The line
FrameLayout from = (FrameLayout) e.getLocalState();
works perfectly fine, so e.getLocalstate already gave the container I wanted. Therefore the parent obtained by view.getParent() was the GridLayout.
I currently have a List View backed by a Simple Adapter. I am able to update the Simple Adapter values fine, however, they do not update on the list view unless the view goes off screen.. then when it returns to the screen it is updated. Ive tried everything like listview.refreshDrawableState and listview.invalidate to simpleadapter.notifyDataSetChanged and nothing makes it update on the screen, the views have to be scrolled off screen then back on to get updated.
Thank you to whoever responds =)
public View getView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
if (v == null)
{
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.machine_list, null);
}
HashMap<String, String> map = machineListView.get(position);
if (map != null)
{
TextView status = (TextView)findViewById(R.id.statusText);
TextView numAlarms = (TextView)findViewById(R.id.alarmText);
if (status != null)
status.setText(map.get(status));
if (numAlarms != null)
status.setText(map.get(numAlarms) + " Alarms");
}
return v;
}
this may not be the best way but I simply reset the listView adapter whenever I want to refresh the whole view.
Can someone tell me what the convertView parameter is used for in the getView() method of the Adapter class?
Here is a sample code take from here:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row, null);
}
Order o = items.get(position);
if (o != null) {
TextView tt = (TextView) v.findViewById(R.id.toptext);
TextView bt = (TextView) v.findViewById(R.id.bottomtext);
if (tt != null) {
tt.setText("Name: "+o.getOrderName()); }
if(bt != null){
bt.setText("Status: "+ o.getOrderStatus());
}
}
return v;
}
What should we pass via convertView?
What I've found, take from here:
Get a View that displays the data at the specified position in the
data set. You can either create a View manually or inflate it from an
XML layout file. When the View is inflated, the parent View (GridView,
ListView...) will apply default layout parameters unless you use
inflate(int, android.view.ViewGroup, boolean) to specify a root view
and to prevent attachment to the root.
Parameters
position -- The position of the item within the adapter's data set of the item whose view we want.
convertView -- The old view to reuse, if possible. Note: You should check that this view is non-null and of an appropriate type before
using. If it is not possible to convert this view to display the
correct data, this method can create a new view.
parent -- The parent that this view will eventually be attached to Returns
returns -- A View corresponding to the data at the specified position.
You shouldn't be calling that method by yourself.
Android's ListView uses an Adapter to fill itself with Views. When the ListView is shown, it starts calling getView() to populate itself. When the user scrolls a new view should be created, so for performance the ListView sends the Adapter an old view that it's not used any more in the convertView param.