您的位置:首页 > 移动开发 > 微信开发

仿微信的语音聊天记录,左右两个布局

2016-10-04 22:21 323 查看
1.微信聊天记录是一个listview,并且分为自己和其他人的两个布局

1.1左侧为其他人的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical"
android:background="#F5F5F5" >

<TextView
android:id="@+id/tv_voice_history_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#DCDCDC"
android:gravity="center"
android:layout_gravity="center_horizontal"
android:minHeight="24dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="2016年09月02日 16:40:00"
android:textColor="#fff"
android:textSize="14dp" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="5dp"
android:paddingTop="5dp">

<ImageView
android:id="@+id/iv_member_portrait"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="10dp"
android:background="@drawable/member_info" />

<LinearLayout
android:id="@+id/ll_voice_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:orientation="vertical" >

<TextView
android:id="@+id/tv_member_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="张星星"
android:textColor="#a0a0a0"
android:textSize="14dp"
android:textStyle="normal" />

<RelativeLayout
android:id="@+id/rl_voice_play"
android:visibility="visible"
android:layout_width="80dp"
android:layout_height="34dp"
android:focusable="false"
android:background="@drawable/selector_voice_history_bg"
>

<ImageView
android:id="@+id/iv_voice_image_anim"
android:layout_width="15dp"
android:layout_height="20dp"
android:background="@anim/voice_history_play_anim"
android:layout_centerVertical="true"
android:layout_marginLeft="18dp"
android:visibility="gone"
/>

<ImageView
android:id="@+id/iv_voice_image"
android:layout_width="15dp"
android:layout_height="20dp"
android:layout_centerVertical="true"
android:layout_marginLeft="18dp"
android:background="@drawable/sound_item"
android:visibility="visible" />

</RelativeLayout>

</LinearLayout>

<TextView
android:id="@+id/tv_voice_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="12 ''"
android:textColor="#a0a0a0"
android:textSize="16dp"
android:textStyle="normal" />

</LinearLayout>

</LinearLayout>

其中的动画是帧动画:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/sound_blank" android:duration="300"/>
<item android:drawable="@drawable/sound_chat_send_one" android:duration="300"/>
<item android:drawable="@drawable/sound_chat_send_two" android:duration="300"/>
<item android:drawable="@drawable/sound_item" android:duration="300"/>

</animation-list>

1.2 右侧是自己的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.andro
cd1c
id.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical"
android:background="#F5F5F5" >

<TextView
android:id="@+id/tv_voice_history_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#DCDCDC"
android:gravity="center"
android:layout_gravity="center_horizontal"
android:minHeight="24dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="2016年09月02日 16:40:00"
android:textColor="#000" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="5dp"
android:paddingTop="5dp">

<View
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="1dp"
/>

<!-- <ImageView
android:id="@+id/iv_unread"
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_marginRight="10dp"
android:background="@drawable/unread_message_circle_shape"
/> -->

<TextView
android:id="@+id/tv_voice_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:text="12 ''"
android:textColor="#a0a0a0"
android:textSize="16dp"
android:textStyle="normal" />

<LinearLayout
android:id="@+id/ll_voice_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:gravity="right"
android:orientation="vertical" >

<TextView
android:id="@+id/tv_member_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我"
android:textColor="#313131"
android:textSize="18dp"
android:textStyle="normal" />

<RelativeLayout
android:id="@+id/rl_voice_play"
android:visibility="visible"
android:layout_width="80dp"
android:layout_height="34dp"
android:focusable="false"
android:gravity="right"
android:background="@drawable/selector_voice_history_bg_right"
>

<ImageView
android:id="@+id/iv_voice_image_anim"
android:layout_width="15dp"
android:layout_height="20dp"
android:layout_marginRight="18dp"
android:background="@anim/voice_history_play_anim_right"
android:layout_centerVertical="true"
android:visibility="visible"
/>

<ImageView
android:id="@+id/iv_voice_image"
android:layout_width="15dp"
android:layout_height="20dp"
android:layout_marginRight="18dp"
android:layout_centerVertical="true"
android:background="@drawable/sound_item_right"
android:visibility="visible" />

</RelativeLayout>

</LinearLayout>

<ImageView
android:id="@+id/iv_member_portrait"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginRight="10dp"
android:background="@drawable/member_info" />

</LinearLayout>

</LinearLayout>

同样是帧动画,只是换成了沿Y轴对称的图片就行。

2.listview的adapter,adapter在填充布局的时候要选择用哪种布局,这里主要用到两个重写的方法getItemViewType()和getViewTypeCount();

/**
* 根据数据源的position返回需要显示的的layout的type
*/
@Override
public int getItemViewType(int position) {

Message msg = myList.get(position);
int type = msg.getType();
Log.e("TYPE:", ""+type);
return type;
}

/**
* 返回所有的layout的数量
*
* */
@Override
public int getViewTypeCount() {
return 2;
}

下面是我的完整的adapter类:
package com.example.listviewchatui;

import java.util.List;

import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
* 想比较原来的多了getItemViewType和getViewTypeCount这两个方法,原来循环使用layout布局,起到了优化的作用
*/
public class MyAdapter extends BaseAdapter implements OnClickListener{

public static final String KEY = "key";
public static final String VALUE = "value";

//因为在getViewTypeCount()方法中返回的是2,所以这两个值只能设置为0和1;切记,切记!否则会报角标越界的。
public static final int VALUE_LEFT = 0;
public static final int VALUE_RIGHT = 1;
private LayoutInflater mInflater;

private Context context;
private List<Message> myList;
private InterClick interClick;
private int mPosition;
private boolean isplaying;
private boolean isSameItem;
public MyAdapter(Context context, List<Message> myList, InterClick interClick){

this.context = context;
this.myList = myList;
this.interClick = interClick;

for(Message msg:myList){
Log.d("myList:", msg.getType()+"");
}

mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

public void addItem(final Message item) {
myList.add(item);
notifyDataSetChanged();
}

@Override
public int getCount() {
return myList.size();
}

@Override
public Object getItem(int arg0) {
return myList.get(arg0);
}

@Override
public long getItemId(int arg0) {
return arg0;
}

@Override
public View getView(int position, View convertView, ViewGroup arg2) {

Message msg = myList.get(position);
int type = getItemViewType(position);
ViewHolder holder = null;

if(convertView == null){
holder = new ViewHolder();

switch (type) {
//左边
case VALUE_LEFT:

convertView = mInflater.inflate(R.layout.item_voice_history_left, null);
// holder.tv_voice_history_time = (TextView)convertView.findViewById(R.id.tv_voice_history_time);
// holder.tv_member_name = (TextView)convertView.findViewById(R.id.tv_member_name);
// holder.tv_member_name.setText(msg.getValue());
// holder.tv_voice_duration = (TextView)convertView.findViewById(R.id.tv_voice_duration);
// holder.iv_voice_image = (ImageView)convertView.findViewById(R.id.iv_voice_image);
// holder.iv_voice_image_anim = (ImageView)convertView.findViewById(R.id.iv_voice_image_anim);

break;

//右边
case VALUE_RIGHT:

convertView = mInflater.inflate(R.layout.item_voice_history_right, null);
// holder.tv_voice_history_time = (TextView)convertView.findViewById(R.id.tv_voice_history_time);
// holder.tv_member_name = (TextView)convertView.findViewById(R.id.tv_member_name);
// holder.tv_member_name.setText(msg.getValue());
// holder.tv_voice_duration = (TextView)convertView.findViewById(R.id.tv_voice_duration);
// holder.iv_voice_image = (ImageView)convertView.findViewById(R.id.iv_voice_image);
// holder.iv_voice_image_anim = (ImageView)convertView.findViewById(R.id.iv_voice_image_anim);

break;

default:
break;
}
convertView.setTag(holder);
}else{
holder = (ViewHolder)convertView.getTag();
}

holder.tv_voice_history_time = (TextView)convertView.findViewById(R.id.tv_voice_history_time);
holder.tv_member_name = (TextView)convertView.findViewById(R.id.tv_member_name);
holder.tv_member_name.setText(msg.getValue());
holder.tv_voice_duration = (TextView)convertView.findViewById(R.id.tv_voice_duration);
holder.iv_voice_image = (ImageView)convertView.findViewById(R.id.iv_voice_image);
holder.iv_voice_image_anim = (ImageView)convertView.findViewById(R.id.iv_voice_image_anim);
holder.ll_voice_play = (LinearLayout)convertView.findViewById(R.id.ll_voice_play);

AnimationDrawable animationDrawable = (AnimationDrawable) holder.iv_voice_image_anim.getBackground();

if (position == mPosition) {
System.out.println("点击的条目======"+position);
if (isSameItem) {
if (isplaying) {
holder.iv_voice_image.setVisibility(View.GONE);
holder.iv_voice_image_anim.setVisibility(View.VISIBLE);
animationDrawable.start();
} else {
holder.iv_voice_image_anim.setVisibility(View.GONE);
holder.iv_voice_image.setVisibility(View.VISIBLE);
animationDrawable.stop();
}
}else {
animationDrawable.start();
holder.iv_voice_image_anim.setVisibility(View.VISIBLE);
holder.iv_voice_image.setVisibility(View.GONE);
}

}else {
System.out.println("其它条目--------"+position);
animationDrawable.stop();
holder.iv_voice_image_anim.setVisibility(View.GONE);
holder.iv_voice_image.setVisibility(View.VISIBLE);
}

holder.ll_voice_play.setOnClickListener(this);

// 设置位置,获取点击的条目按钮
holder.ll_voice_play.setTag(position);

return convertView;
}

/**
* 根据数据源的position返回需要显示的的layout的type
*/
@Override
public int getItemViewType(int position) {

Message msg = myList.get(position);
int type = msg.getType();
Log.e("TYPE:", ""+type);
return type;
}

/**
* 返回所有的layout的数量
*
* */
@Override
public int getViewTypeCount() {
return 2;
}

class ViewHolder{

public LinearLayout ll_voice_play;
public ImageView iv_voice_image_anim;
public ImageView iv_voice_image;
public TextView tv_voice_duration;
public TextView tv_member_name;
public TextView tv_voice_history_time;

}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.ll_voice_play:
interClick.animClick(v);
break;
default:
break;
}
}

public void refreshPersonContactsAdapter(int mPosition, boolean isplaying,
boolean isSameItem) {
this.mPosition = mPosition;
this.isplaying = isplaying;
this.isSameItem = isSameItem;
notifyDataSetChanged();
}

}


同样的里面也用到了接口,来实现语音播放时的动画效果,接口类如下:
package com.example.listviewchatui;

import android.view.View;

public interface InterClick {
public void animClick(View v);
}


3.activity中为listview设置adapter,并监听条目中的按钮或布局的点击事件;

package com.example.listviewchatui;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.BaseAdapter;
import android.widget.ListView;

public class MainActivity extends Activity {

private ListView lvData;
private boolean isplaying;
private boolean isSameItem;
private int mPosition = -1;
private int lastPosition = -1;
private MyAdapter myAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

lvData = (ListView)findViewById(R.id.lv_data);

lvData.setAdapter(getAdapter());
}

private BaseAdapter getAdapter(){
myAdapter = new MyAdapter(this, getMyData(), interClick);
return myAdapter;
}

private List<Message> getMyData(){

List<Message> msgList = new ArrayList<Message>();
Message msg;

msg = new Message();
msg.setType(MyAdapter.VALUE_LEFT);
msg.setValue("别人");
msgList.add(msg);

msg = new Message();
msg.setType(MyAdapter.VALUE_RIGHT);
msg.setValue("自己");
msgList.add(msg);

msg = new Message();
msg.setType(MyAdapter.VALUE_LEFT);
msg.setValue("别人");
msgList.add(msg);

msg = new Message();
msg.setType(MyAdapter.VALUE_RIGHT);
msg.setValue("自己");
msgList.add(msg);

msg = new Message();
msg.setType(MyAdapter.VALUE_LEFT);
msg.setValue("别人");
msgList.add(msg);

msg = new Message();
msg.setType(MyAdapter.VALUE_RIGHT);
msg.setValue("自己");
msgList.add(msg);

msg = new Message();
msg.setType(MyAdapter.VALUE_LEFT);
msg.setValue("别人");
msgList.add(msg);

msg = new Message();
msg.setType(MyAdapter.VALUE_RIGHT);
msg.setValue("自己");
msgList.add(msg);

msg = new Message();
msg.setType(MyAdapter.VALUE_LEFT);
msg.setValue("别人");
msgList.add(msg);

msg = new Message();
msg.setType(MyAdapter.VALUE_RIGHT);
msg.setValue("自己");
msgList.add(msg);

return msgList;

}

private InterClick interClick = new InterClick() {
@Override
public void animClick(View v) {
mPosition = (Integer) v.getTag();
if (lastPosition == mPosition) {
isSameItem = true;
isplaying = !isplaying;
} else {
isSameItem = false;
isplaying = true;
}
myAdapter.refreshPersonContactsAdapter(mPosition, isplaying, isSameItem);
lastPosition = mPosition;
}
};

}


Message只是一个JavaBean对象,可以根据自己的需要设置对象。
这里只是写了2种不同的布局,更多详细的布局可以参考:http://blog.csdn.net/cleanness/article/details/24722403
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: