I am trying do the chatting application. When send a message that should be in right side , received message should be in left side. I have done everything in good manner. when I add new value in list view , previous value has fluctuated. Please can any one solve my problem ? I have attached my source code.
Main Activity :
public class MainActivity extends AppCompatActivity {
ArrayList<ChatData> data = new ArrayList<ChatData>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ListView listView = (ListView) findViewById(R.id.list_item);
final ChatAdaptor chatAdaptor = new ChatAdaptor(this, getDetails());
listView.setAdapter(chatAdaptor);
listView.setDivider(null);
ImageView imageView = (ImageView) findViewById(R.id.submit);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
EditText objText = (EditText) findViewById(R.id.text_msg);
chatAdaptor.add(new ChatData(objText.getText().toString(), false));
listView.setSelection(chatAdaptor.getCount() - 1);
objText.setText(null);
// chatAdaptor.notifyDataSetChanged();
}
});
}
public ArrayList<ChatData> getDetails() {
data.add(new ChatData("Hi! Agent", false));
data.add(new ChatData("Hi! Agent ,Are you there ", false));
data.add(new ChatData("Yeah tell me how can I help you", true));
data.add(new ChatData("I am getting wrong balance", false));
return data;
}
}
Custom adapter:
public class ChatAdaptor extends ArrayAdapter<ChatData> {
private Activity activity;
String TAG = "bks";
private List<ChatData> originalData = null;
public ChatAdaptor(Activity activity, ArrayList<ChatData> objects) {
super(activity, 0, objects);
this.activity = activity;
this.originalData = objects;
}
#Override
//called when rendering the list
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
// convertView = mInflater.inflate(R.layout.search_data, true,null);
LayoutInflater inflater = activity.getLayoutInflater();
convertView = inflater.inflate(R.layout.test, null, false);
if (originalData.get(position).isAgentMsg())
convertView = inflater.inflate(R.layout.show_chat_agent, null, true);
else
convertView = inflater.inflate(R.layout.show_chat_client, null, true);
// Creates a ViewHolder and store references to the three views
// we want to bind data to.
holder = new ViewHolder();
holder.objMsg = ( TextView ) convertView.findViewById(R.id.msg) ;
// Bind the data efficiently with the holder.
convertView.setTag(holder);
} else {
// Get the ViewHolder back to get fast access to the TextView
holder = (ViewHolder) convertView.getTag();
}
holder.objMsg.setText(originalData.get(position).getMsg());
return convertView;
}
static class ViewHolder {
TextView objMsg;
/** TextView objClientText, objAgentText;
ImageView objClientImage1, objClientImage2;
ImageView objAgentImage1, objAgentImage2;
*/
}
}
Thanks
Kalanidhi M
Just change this line in your getView method
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.test, parent, true);
if (originalData.get(position).isAgentMsg())
convertView = inflater.inflate(R.layout.show_chat_agent, parent, true);
else
convertView = inflater.inflate(R.layout.show_chat_client, parent, true);
Related
I have two ArrayList namely "one" and "two" ["two" is always a sub-set of "one"], And i have a list view which is populating by Arraylist "one". Now am checking condition that if element of "two" is present in "one", then set ImageButton in list view and if not the set Button in list view.
Below is my getView method. Any help or keywords will be appreciated.
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(context);
//HERE HOW TO SWITCH TWO LAYOUTS..
convertView = inflater.inflate(R.layout.invite_row, null);
viewHolder = new ViewHolder();
viewHolder.name = (TextView)convertView.findViewById(R.id.textView6);
viewHolder.text = (TextView) convertView.findViewById(R.id.childTextView);
viewHolder.button = (Button) convertView
.findViewById(R.id.childButton);
Typeface typeFace= Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Bold.ttf");
viewHolder.name.setTypeface(typeFace);
// viewHolder.button.setBackgroundResource(R.drawable.invitebuttonbackground);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
final String temp = getItem(position);
final String tempname = getItem(position);
viewHolder.name.setText(tempname);
viewHolder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (customListner != null) {
customListner.onButtonClickListner(position, temp, tempname);
}
}
});
return convertView;
}
one thing you can do is
View convertView;
if (whatever condition) {
convertView = inflater.inflate(R.layout.invite_row, null);
} else {
convertView = inflater.inflate(R.layout.invite_row_two, null);
}
if you can post your layout , i will have clear undestanding of what you want to doing.
I have a custom adapter class for a listview and I want to be able to access the content of a specific row by clicking a button on it. I tried to create a ViewHolder, but I get a NPE error when I try to click it.
static class ViewHolder {
TextView camera;
TextView players;
TextView max_players;
ImageView privata;
Button Buton;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
String variabile[] = getItem(position).split("\\s+");
LayoutInflater linflater = LayoutInflater.from(getContext());
View customView = linflater.inflate(R.layout.custom_row, parent, false);
final ViewHolder holder = new ViewHolder();
holder.camera = (TextView) customView.findViewById(R.id.Nume);
holder.players = (TextView) customView.findViewById(R.id.players);
holder.max_players = (TextView) customView.findViewById(R.id.max_players);
holder.privata = (ImageView) customView.findViewById(R.id.privata);
holder.Buton = (Button) customView.findViewById(R.id.Buton);
holder.camera.setText(variabile[0]);
if (!variabile[1].equals("true")) {
parola = false;
holder.privata.setVisibility(View.INVISIBLE);
}
holder.players.setText(variabile[2]);
holder.max_players.setText(variabile[3]);
room_id = variabile[4];
nume = variabile[5];
holder.Buton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
hash = new HashMap<String, String>();
hash.put("name", nume);
hash.put("room", room_id);
if (intra) {
holder.Buton.setText("Iesi");
site = siteul + "/join";
intra = false;
} else {
holder.Buton.setText("Intra");
site = siteul + "/leave";
intra = true;
}
new ATask().execute(site);
}
});
return customView;
}
When using the ViewHolder pattern, you should check if the convertView in null or has been created before, in the getView method, and after that use setTag and getTag methods. like this :
if (convertView == null)
{
LayoutInflater linflater = LayoutInflater.from(getContext());
convertView = linflater.inflate(R.layout.your_list_item_view, parent, false);
viewHolder.textView = (TextView)convertView.findViewById([the id]);
.
.
.
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
You need to check if the convertView is null so it is already has been visited or not then store the holder in tag Like
ViewHolder holder;
if (convertView == null) {
LayoutInflater linflater = LayoutInflater.from(getContext());
holder = linflater.inflate(R.layout.custom_row, parent, false);....
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}//Common code
I have
public class MainActivity extends FragmentActivity
I wrote Loader class which implements AsyncResponse:
public class Loader implements AsyncResponse {
public Activity contextActivity;
Loader(Activity context) {
this.contextActivity = context;
}
Class "Loader" has method "DrawTabInfo" which calling from AsyncResponse callback.
public void drawTabInfo(String jsonBlob, int tabId)
{
JSONObject dataJsonObj;
PullToRefreshListView list = null;
try {
dataJsonObj = new JSONObject(jsonBlob);
JSONArray jsonData = dataJsonObj.getJSONArray("steals");
ArrayList<JSONObject> data = new ArrayList<JSONObject>();
for (int i=0;i<jsonData.length();i++){
data.add(jsonData.getJSONObject(i));
}
Adapter adapter = new Adapter(contextActivity, data);
LayoutInflater inflater = LayoutInflater.from(contextActivity);
if (tabId == 0) {
View view = inflater.inflate(R.layout.listviewlayout, null, false);
list = (PullToRefreshListView) view.findViewById(R.id.listView);
}
if (tabId == 1) {
View view = inflater.inflate(R.layout.listviewlayout2, null, false);
list = (PullToRefreshListView) view.findViewById(R.id.listView2);
}
list.setAdapter(adapter);
adapter.setNotifyOnChange(true);
Log.d("COUNT") shows - "4", what means array is built fine.
public class Adapter extends ArrayAdapter<JSONObject> {
private final Activity context;
private final ArrayList<JSONObject> profiles;
public String header;
public String preText;
public String imageURL;
static class ViewHolder {
public TextView header;
public ImageView image;
public TextView preText;
public LinearLayout linearItemLayout;
}
public Adapter(Activity context, ArrayList<JSONObject> array) {
super(context, R.layout.tab1_list_layout, array);
Log.d("ADAPTER", "SETTING ADAPTER");
this.context = context;
this.profiles = array;
Log.d("COUNT", "" + profiles.size());
}
#Override
public int getCount()
{
return profiles.size();
}
My getView method:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
Log.i("GetView Log", "Adapters GetView hasbeen called");// thats never calling
if (rowView == null) {
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.tab1_list_layout, null);
ViewHolder viewHolder = new ViewHolder();
viewHolder.linearItemLayout = (LinearLayout) rowView.findViewById(R.id.linearItemLayout);
viewHolder.header = (TextView) rowView.findViewById(R.id.itemHeader);
viewHolder.image = (ImageView) rowView.findViewById(R.id.itemPreImage);
viewHolder.preText = (TextView) rowView.findViewById(R.id.itemPreText);
rowView.setTag(viewHolder);
}
ViewHolder holder = (ViewHolder) rowView.getTag();
JSONObject item = null;
try {
item = profiles.get(position);
header = item.getString("header");
preText = item.getString("previewText");
imageURL = item.getString("previewImageUrl");
} catch (JSONException e) {
e.printStackTrace();
}
Log.d("ADAPTER LOG", header);
holder.header.setText(header);
holder.preText.setText(preText);
int headerHeight = (int) Math.round(header.length() * 1.5);
holder.linearItemLayout.setMinimumHeight(40 + headerHeight + preText.length());
Picasso.with(context).setIndicatorsEnabled(true);
Picasso.with(context).load(imageURL).resize(140,100).into(holder.image);
return rowView;
}
In MainActivity i calling, where "this" = MainActivity;
Loader loader = new Loader(this);
loader.loadTabInfo(0);
Method getView never calling. What I'am doing wrong?
UPD:
Solved:
public void drawTabInfo(String jsonBlob, int tabId)
{
JSONObject dataJsonObj;
PullToRefreshListView list = null;
try {
dataJsonObj = new JSONObject(jsonBlob);
JSONArray jsonData = dataJsonObj.getJSONArray("steals");
ArrayList<JSONObject> data = new ArrayList<JSONObject>();
for (int i=0;i<jsonData.length();i++){
data.add(jsonData.getJSONObject(i));
}
Adapter adapter = new Adapter(contextActivity, data);
//LayoutInflater inflater = LayoutInflater.from(contextActivity);
if (tabId == 0) {
//View view = inflater.inflate(R.layout.listviewlayout, null, false);
list = (PullToRefreshListView) contextActivity.findViewById(R.id.listView);
Your code is fine .. just you need a little bit change in get view method
add a return statement.. like return rowView;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
Log.d("GETVIEaW", "GETVIEW");
if (rowView == null) {
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.tab1_list_layout, null);
ViewHolder viewHolder = new ViewHolder();
viewHolder.linearItemLayout = (LinearLayout) rowView.findViewById(R.id.linearItemLayout);
viewHolder.header = (TextView) rowView.findViewById(R.id.itemHeader);
viewHolder.image = (ImageView) rowView.findViewById(R.id.itemPreImage);
viewHolder.preText = (TextView) rowView.findViewById(R.id.itemPreText);
rowView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) rowView.getTag();
}
viewHolder.preText.setText("Type your name");
return rowView;
}
Are you sure that Log.d() is not called? You may want to change logging scope, usually default scope is info and it doesn't show debug messages. You can try to use Log.i() or change scope.
Try posting your adapter.setNotifyOnChange(true); to handler. Follow this link
I have an android app where i want to display some messages.The messages are classified into two categories, images and text.Text messages have two types,sent and received.I have created a custom listview adapter to display the messages in a listview.When calling the adapter,i pass an arraylist of 13 objects.Problem is not all the messages in arraylist are displayed.Only the first five messages are displayed.The messages are displayed three times each.When a message item in the listview is clicked,more than one message is highlited.What could be the problem.
Here is the listview adapter:
public class CustomMessageListAdapter extends BaseAdapter {
private ArrayList<?> listData;
private LayoutInflater layoutInflater;
public CustomMessageListAdapter(Context context, ArrayList<?> listData) {
this.listData = listData;
layoutInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return listData.size();
}
#Override
public Object getItem(int position) {
return listData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.listview_message,
null);
viewHolder = new ViewHolder();
viewHolder.incoming_message = (RelativeLayout) convertView
.findViewById(R.id.received_layout);
viewHolder.outgoing_message = (RelativeLayout) convertView
.findViewById(R.id.sent_layout);
viewHolder.sent_message = (TextView) convertView
.findViewById(R.id.sent_messages_textView_message);
viewHolder.sent_time = (TextView) convertView
.findViewById(R.id.sent_messages_textview_time);
viewHolder.sent_image = (ImageView) convertView
.findViewById(R.id.sent_image_imageview);
viewHolder.received_image = (ImageView) convertView
.findViewById(R.id.received_image_imageview);
viewHolder.sent_image_layout = (RelativeLayout) convertView
.findViewById(R.id.sent_image_layout);
viewHolder.received_image_layout = (RelativeLayout) convertView
.findViewById(R.id.received_image_layout);
viewHolder.received_message = (TextView) convertView
.findViewById(R.id.messages_textView_message);
viewHolder.received_time = (TextView) convertView
.findViewById(R.id.messages_textview_time);
viewHolder.date = (TextView) convertView
.findViewById(R.id.messages_textView_date);
viewHolder.sent_hepasnap = (RelativeLayout) convertView
.findViewById(R.id.chat_layout_sent_hepasnap);
viewHolder.recieved_hepasnap = (RelativeLayout) convertView
.findViewById(R.id.chat_layout_received_hepasnap);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
MessageItem messageItem = (MessageItem) listData.get(position);
Log.i("msg", "" + position);
if (messageItem.getCategory().equalsIgnoreCase("text")) {
if (messageItem.getType().equalsIgnoreCase("sent")) {
viewHolder.outgoing_message.setVisibility(View.VISIBLE);
viewHolder.sent_message.setText(messageItem.getMessage());
viewHolder.sent_time.setText(messageItem.getTime());
} else {
viewHolder.incoming_message.setVisibility(View.VISIBLE);
viewHolder.received_message.setText(messageItem.getMessage());
viewHolder.received_time.setText(messageItem.getTime());
}
}
return convertView;
}
public class ViewHolder {
TextView sent_message;
TextView sent_time;
TextView received_message;
TextView received_time;
RelativeLayout outgoing_message;
RelativeLayout incoming_message;
RelativeLayout sent_hepasnap;
RelativeLayout recieved_hepasnap;
TextView date;
ImageView sent_image;
ImageView received_image;
RelativeLayout sent_image_layout;
RelativeLayout received_image_layout;
}
}
And when message is clicked:
add viewHolder.incoming_message.setVisibility(View.GONE); to if condition
(messageItem.getType().equalsIgnoreCase("sent"))
and viewHolder.outgoing_message.setVisibility(View.GONE); to else condition.
If your Problem not solved then let me know.
I think the messages are getting displayed multiple times because they carry older values whenever convert view is non-null.
And since your incoming and outgoing messages are both getting filled it is giving the illusion of multiple items getting selected.
So you should change visibility of unused views to View.GONE.
How can I display text in TextView at get view after this call
ListAdapter adapter = new MyCustomAdapter (
ManageSection.this, studentList,
R.layout.list_student, new String[] { TAG_StudentID,
TAG_StudentNo,TAG_FullName},
new int[] { R.id.StudentID, R.id.StudentNo,R.id.FullName});
setListAdapter(adapter);
and the class MyCustomAdapter has a get view, I will display the text
holder.FullName= (TextView) convertView.findViewById(R.id.FullName);
holder.FullName.setText();
holder.StudentNo=(TextView) convertView.findViewById(R.id.StudentNo);
holder.StudentNo.setText();
So at set text what should I write cause I do
no=student.get(holder.position).get(TAG_StudentNo);
name =student.get(holder.position).get(TAG_FullName);
and take no, name but the text is duplicated in the whole list
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if(convertView==null)
{
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(resource, parent, false);
holder = new ViewHolder();
no=student.get(holder.position).get(TAG_StudentNo);
name =student.get(holder.position).get(TAG_FullName);
holder.StudentID= (TextView) convertView.findViewById(R.id.StudentID);
holder.FullName= (TextView) convertView.findViewById(R.id.FullName);
holder.FullName.setText();
holder.StudentNo=(TextView) convertView.findViewById(R.id.StudentNo);
holder.StudentNo.setText();
holder.DeleteStudent = (ImageView) convertView.findViewById(R.id.DeleteStudent);
holder.AlertIcon = (ImageView) convertView.findViewById(R.id.Alert);
// add a listener for phone call
holder.DeleteStudent.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
id = student.get(holder.position).get(TAG_StudentID);
Toast.makeText(getContext(),id,Toast.LENGTH_LONG).show();
}
});
holder.AlertIcon.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// String email = MyCustomAdapter.listMap.get(holder.position).get("email");
// ActivityHelper.startActivity(ActivityManager.EMAIL, email);
}
});
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.position = position;
return convertView;
}
private static class ViewHolder
{
ImageView DeleteStudent;
ImageView AlertIcon;
TextView StudentID, StudentNo ,FullName;
int position;
}
}
Can anyone tell me what the problem is here?
Try this code.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if(convertView==null)
{
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(resource, parent, false);
holder = new ViewHolder();
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.position = position;
no=student.get(holder.position).get(TAG_StudentNo);
name =student.get(holder.position).get(TAG_FullName);
holder.StudentID= (TextView) convertView.findViewById(R.id.StudentID);
holder.FullName= (TextView) convertView.findViewById(R.id.FullName);
holder.FullName.setText();
holder.StudentNo=(TextView) convertView.findViewById(R.id.StudentNo);
holder.StudentNo.setText();
holder.DeleteStudent = (ImageView) convertView.findViewById(R.id.DeleteStudent);
holder.AlertIcon = (ImageView) convertView.findViewById(R.id.Alert);
// add a listener for phone call
holder.DeleteStudent.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
id = student.get(holder.position).get(TAG_StudentID);
Toast.makeText(getContext(),id,Toast.LENGTH_LONG).show();
}
});
holder.AlertIcon.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// String email = MyCustomAdapter.listMap.get(holder.position).get("email");
// ActivityHelper.startActivity(ActivityManager.EMAIL, email);
}
});
return convertView;
}
private static class ViewHolder
{
ImageView DeleteStudent;
ImageView AlertIcon;
TextView StudentID, StudentNo ,FullName;
int position;
}
}
What you were doing is just setting the data only when the convertView is null and if not you just returning the view after some Holder operation. You need to set Text etc, in the textView in every case. If you need more explanation, please ask.
its simple buddy U just have to put this line instead of blank setText()
no=student.get(holder.position).get(TAG_StudentNo);// the roll_number string
name =student.get(holder.position).get(TAG_FullName);//full name string
holder.StudentID= (TextView) convertView.findViewById(R.id.StudentID);
holder.FullName= (TextView) convertView.findViewById(R.id.FullName);
holder.FullName.setText(name);//pass fullname
holder.StudentNo=(TextView) convertView.findViewById(R.id.StudentNo);
holder.StudentNo.setText(no);//pass roll no.
you just have to pass the no and 'namevariable tosetText()` method.