I have his following code:
public class MySimpleArrayAdapter extends ArrayAdapter {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.todo_list, parent, false);
TextView titleTextView = (TextView) rowView
.findViewById(R.id.todo_row_title);
TextView dateTextView = (TextView) rowView
.findViewById(R.id.todo_row_date);
ImageView imageView = (ImageView) rowView
.findViewById(R.id.todo_row_image);
titleTextView.setText(mTitles[position]);
..
}
and this content:
mTitles = [עברית, english, עברית]
meaning some strings in hebrew, and some in english
I run this on my physical device.
However in the UI is see only dates strings. How can I enable hebrew viewing?
Other apps on my mobile shows hebrew.
You will need an internationalization library to handle language conversions.
Gettext-Commons is a popular one, there are many others.
https://code.google.com/p/gettext-commons/
Here is an example that demonstrates how easy it is to use the Gettext Commons:
I18n i18n = I18nFactory.getI18n(getClass());
System.out.println(i18n.tr("This text will be translated"));
Related
I have a dynamic adapter that fills up a listview with textviews with values read from a JSON file, here is an example ( https://imgur.com/a/w9CHzxX ). Now I need to gather the user input from those fields and use it in a later part of my application, but my question is. when i generate textviews like that they all have the same ID right? so how can i specificly gather the user input of lets say the 2nd textview?
Adapter
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {if (convertView == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.layout_question_textfield, null, true);
---> holder.editText = (AutoCompleteTextView) convertView.findViewById(R.id.edt);
---> holder.editTitel = (Button) convertView.findViewById(R.id.btn);
convertView.setTag(holder);
}
else {...}
holder.editText.setHint(HintArrayList.get(position).getEditTextValue());
ID is an attribute of a view that scope of this attribute is limited by the inflated view group that includes this view.
for example if we have this xml file (item_view.xml):
<LinearLayout
...>
<TextView
...
android:id="#+id/textView_itemVew"/>
</LinearLayout>
and then we inflate this file several times (maybe in an adapter class) as below:
View item1 = inflater.inflate(R.layout.item_view, null,true);
View item2 = inflater.inflate(R.layout.item_view, null,true);
View item3 = inflater.inflate(R.layout.item_view, null,true);
now we can access the TextView view by it's ID but we should use the view group of this TextView to find it.
//Id's are the same but view groups no!
TextView editText_of_item1 = item1.findViewById(R.id.editText_itemVew);.
TextView editText_of_item2 = item2.findViewById(R.id.editText_itemVew);
TextView editText_of_item3 = item3.findViewById(R.id.editText_itemVew);
.
.
.
in your case you can add each EditText to a list to access it after whole list inflated ... like this:
List<EditText> editTextList = new ArrayList<>();
public View getView(int position,View view,ViewGroup parent) {
LayoutInflater inflater=context.getLayoutInflater();
View itemView = inflater.inflate(R.layout.item_view, null,true);
EditText itemEditText = (EditText) itemView.findViewById(R.id.editText);
editTextList.add(itemEditText);
return itemView;
};
there is useful example in javaTpoint website for you.
The textView which in every tablayout could not be changed to some text.
No errors etc. happen. here is the code.
Each tab layout are in different files .xml.
LayoutInflater inflater = getLayoutInflater();
View view = inflater.inflate(R.layout.coordinators_tab, null,false);
TextView txt = view.findViewById(R.id.textView4);
txt.setText("JUST WE CAN");
Please don't dislike this question if don't understand it!
Access the views only after the fragment is created.In oncreateview after view is inflated access the views.
public class CoordinatorsTab extends Fragment {
private static final String TAG = "CoordinatorsTab";
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.coordinators_tab, container, false);
//Access here
TextView txt = view.findViewById(R.id.textView4);
txt.setText("JUST WE CAN");
return View;
}
}
After you find a view you have to cast it like this
TextView txt = (TextView) view.findViewById(R.id.textView4);
Alright so this may already be a thread but I still have yet to find a thread that answers my questions!
this is my code.
LayoutInflater inflater = (LayoutInflater)getApplicationContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
So I get an error on"getApplicationContext()"and".getSystemService()" because I don't think they're defined or anything like that but I wouldn't know what to do or where to go to define it...?
someone help pls
This is the actual code for this method:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
String message = myArrayList.get(position);
LayoutInflater inflater = (LayoutInflater)getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View myLayout = inflater.inflate(R.layout.chat_activity, null);
TextView messageTextView = (TextView) myLayout.findViewById(R.id.chat_function);
messageTextView.setText(message);
convertView = myLayout;
return convertView;
and the error is simple and it's basically "Cannot resolve method etc etc" but I don't really know what to do now knowing that that's the error!!
When I create a class extends BaseAdapter, I get a warning message
Unconditional layout inflation from view adapter: Should use View Holder pattern (use recycled view passed into this method as the second parameter) for smoother scrolling
Do I need to change my code like this suggestion? All my code is running smoothly, it's just whether it is necessary to change the code to do updata code with the latest styles? Or just need to add #SuppressLint({ "ViewHolder", "InflateParams" }) ?
My adapter
public View getView(int position, View convertView, ViewGroup parent) {
View v = inflater.inflate(R.layout.list_item, null);
TextView merchant_type = (TextView) v.findViewById(R.id.merchant_type);
TextView merchant_name = (TextView) v.findViewById(R.id.merchant_name);
TextView merchant_location = (TextView) v.findViewById(R.id.merchant_location);
VoucherBean obj = (VoucherBean) getItem(position);
merchant_type.setText(obj.getMerchantType());
merchant_name.setText(obj.getMerchantName());
merchant_location.setText(obj.getMerchantLocation());
return v;
}
If you want to change my code as recommended above warning, like what my code later? Sorry if my question is too basic for a beginner
if you have more data in your list view then you should use recycling, because it improves scrolling and performance also. here is code look like if you use view holder in your adapter.
your ViewHolder looks like
public class ViewHolder {
public TextView merchant_type;
public TextView merchant_name;
public TextView merchant_location;
}
and your getView method
View vi = convertView;
ViewHolder holder;
if (convertView == null) {
vi = inflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.merchant_type = (TextView) vi.findViewById(R.id.merchant_type);
holder.merchant_name = (TextView) vi.findViewById(R.id.merchant_name);
holder.merchant_location = (TextView) vi.findViewById(R.id.merchant_location);
vi.setTag(holder);
} else
holder = (ViewHolder) vi.getTag();
// now set your text view here like
holder.merchant_name.setText("Bla Bla Bla");
// return your view
return vi;
The View Holder pattern is meant to make your code easier to read and to maintain. If you look at the standard ViewHolder you'll see that its a class that basically does what you do in your getView:
private static class ExampleViewHolder{
TextView merchant_type;
TextView merchant_name;
TextView merchant_location;
public ExampleViewHolder(View view){
merchant_type = (TextView) v.findViewById(R.id.merchant_type);
merchant_name = (TextView) v.findViewById(R.id.merchant_name);
merchant_location = (TextView) v.findViewById(R.id.merchant_location);
}
}
Then in your getView method you'd get your view like this:
ExampleViewHolder holder = new ExampleViewHolder(view);
view.setTag(holder);
It's good to have them and the newer apis kind of force the use of this pattern, however as you can see by the code it doesn't change much besides readability and ease of maintenance.
However! There is an important part of the getView method that you are missing, and is most likely the reason for the warning.
The listview recycles the views, and gives them back to the adapter so that the same view doesnt have to be inflated everytime. Saves resources and a lot of memory, and you're not making use of this very important aspect of the listView.
You see, the way it recycles views is passing the old view, that you inflated before, back to the adapter through the convertView, so if the convertView is not null you can be sure its the inflated layout that you are using. So use that instead of inflating a new one:
View view = convertView;
ExampleViewHolder holder;
if(view == null){//means convertView is also null
view = inflater.inflate(yourlayout, parent, false);
holder = new ExampleViewHolder(view);
view.setTag(holder);
}else{
holder = (ExampleViewHolder) view.getTag();
}
I know that many similar questions have been posted on stackoverflow, so please don't think I haven't searched high and low. I think my problems simply comes from now completely understanding listViews and the lifecycles of list items. I have a list view that can contain two types of messages, outbound or inbound. Originally, my listView would use a different background color depending on the type of message (outbound vs inbound), and it worked flawlessly. Now my application doesn't require a different background for list items, but it actually requires different layouts for different list items.
This is a clip of my Adapter.
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
SoapBoxMessage thisMessage = messages.get(position);
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (thisMessage.isOutbound()) {
v = inflater.inflate(R.layout.outbound_row, null);
} else {
v = inflater.inflate(R.layout.inbound_row, null);
}
}
Adapters can support different ViewItemTypes that will solve your recycling problems.
static public enum LAYOUT_TYPE {
INBOUND,
OUTBOUND
}
#Override
public int getViewTypeCount () {
return LAYOUT_TYPE.values().length;
}
#Override
public int getItemViewType (int position) {
if ( messages.get(position).isOutbound())
return LAYOUT_TYPE.OUTBOUND.ordinal();
else
return LAYOUT_TYPE.INBOUND.ordinal();
}
#Override
public View getView (int position, View convertView, ViewGroup parent) {
LAYOUT_TYPE itemType = LAYOUT_TYPE.values()[getItemViewType(position)];
... (code until inflater )
switch (itemType){
case INBOUND:
convertview = /inflate & configure inbound layout
break;
case OUTBOUND:
convertview = /inflate & configure outbound layout
break;
}
you don't need to worry about recycling views because the listview will respect the ViewItemTypes for each position and it will only provide a convertview of the correct viewtype for that position
The problem is that listview is recycling the view so when you check if the view is null it wont pass that because the view is not null when it is recycled
you would need to inflate the view each time getView is called, basically removing if(v == null)
Try to use a ViewHolder like this:
ViewHolder holder;
public View getView(int position, View convertView, ViewGroup parent) {
convertView = null;
SoapBoxMessage thisMessage = messages.get(position);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (thisMessage.isOutbound()) {
convertView = inflater.inflate(R.layout.outbound, null, false);
//specific to your outbound layout
holder = new ViewHolder();
holder.text= (TextView)convertView.findViewById(R.id.textview);
holder.group = (RadioGroup)convertView.findViewById(R.id.toggleGroup);
holder.toggle = (ToggleButton)convertView.findViewById(R.id.toggleButton);
} else {
convertView = inflater.inflate(R.layout.inbound, null, false);
//specific to your inbound layout
holder = new ViewHolder();
holder.text= (TextView)convertView.findViewById(R.id.textview);
holder.group = (RadioGroup)convertView.findViewById(R.id.toggleGroup);
holder.toggle = (ToggleButton)convertView.findViewById(R.id.toggleButton);
}
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
//Here you can set the text or other code you want to implement
holder.text.setText("Whatever!");
return convertView;
}
static class ViewHolder {
//TODO put components you use like:
TextView text;
RadioGroup group;
ToggleButton toggle;
}
It's because of the recycling that is happening. You would need something along these lines:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
SoapBoxMessage thisMessage = messages.get(position);
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.listview_feedlog_item, null);
holder = new ViewHolder();
holder.txtTime = (TextView) convertView.findViewById(R.id.textTime);
holder.txtDate = (TextView) convertView.findViewById(R.id.textDate);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
// I don't know how your SoapBoxMessage is made up so here are two sample methods
holder.txtTime.setText(thisMessage.getTime());
holder.txtDate.setText(thisMessage.getDate());
return convertView;
}
/* private view holder class */
private class ViewHolder {
TextView txtTime;
TextView txtDate;
}
Also, remember to always reset or initiate a value in the getView method. Since a View can be recycled it might carry with it properties of its former life.
Whether this is a good practice or not, Removing if (v == null) will solve the problem.
Anyway, you will have to re-inflate the view.