仿QQ电话/消息切换的自定义布局结合Fragment解决你的需求!

转载请注明出处:王亟亟的大牛之路
先上模仿的对象:QQ的电话/消息 界面

用户点击消息或者电话会切换不同的界面

然后再上自己实现的界面

然后再附带了一些每一个Fragment内部的操作,来模拟切换后的效果

实现方法: 一个自定义控件+下面的Fragment.利用setOnSegmentControlViewClickListener方法来监听用户的点击来对界面进行操作。

项目目录结构

一个主Activity加一系列分页的Fragment(其实这里可以用Java代码来添加Fragment,但是考虑到大家的使用性,还是用麻烦的方法。毕竟 Copy走就直接可以改每一个单独的Fragment进行修改了)

主Activity

package com.wjj.wjjdemo;
import com.wjj.wjjdemo.customView.SegmentControlView;
import com.wjj.wjjdemo.customView.SegmentControlView.onSegmentControlViewClickListener;
import com.wjj.wjjdemo.fragment.fragmenta;
import com.wjj.wjjdemo.fragment.fragmentb;
import com.wjj.wjjdemo.fragment.fragmentc;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

public class MainActivity extends Activity {
    private SegmentControlView SegmentControlView = null;
    /*等会要用于切换的3个Fragment*/
    private fragmenta fragmenta;
    private fragmentb fragmentb;
    private fragmentc fragmentc;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FindById();
     // 设置默认的Fragment
        setDefaultFragment();
        Listener();
    }

    private void FindById(){
        SegmentControlView = (SegmentControlView) findViewById(R.id.SegmentControlView);
    }

    private void Listener(){
        SegmentControlView.setOnSegmentControlViewClickListener(new onSegmentControlViewClickListener() {

            @Override
            public void onSegmentControlViewClick(View view, int position) {
                FragmentManager fm = getFragmentManager();
                // 开启Fragment事务
                FragmentTransaction transaction = fm.beginTransaction(); 

                switch (position) {
                    case 0:
                        if (fragmenta == null)
                        {
                            fragmenta = new fragmenta();
                        }
                        // 使用当前Fragment的布局替代id_content的控件
                        transaction.replace(R.id.fragmentlayout, fragmenta);
                        // 事务提交
                        transaction.commit();
                        break;
                    case 1:
                     if (fragmentb == null)
                        {
                            fragmentb = new fragmentb();
                        }
                        // 使用当前Fragment的布局替代id_content的控件
                        transaction.replace(R.id.fragmentlayout, fragmentb);
                        // 事务提交
                        transaction.commit();
                        break;
                    case 2:
                     if (fragmentc == null)
                        {
                            fragmentc = new fragmentc();
                        }
                        // 使用当前Fragment的布局替代id_content的控件
                        transaction.replace(R.id.fragmentlayout, fragmentc);
                        // 事务提交
                        transaction.commit();
                        break;
                    default:
                        break;
                }
            }
        });
    }

    private void setDefaultFragment(){
        FragmentManager fm = getFragmentManager();
        FragmentTransaction transaction = fm.beginTransaction();
        fragmenta=new fragmenta();
        transaction.replace(R.id.fragmentlayout, fragmenta);
        transaction.commit();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

其实 当中监听时间的transaction.commit(); 些多余了,大家就自行修改吧,放到函数外面就行了,因为会break出去,并不需要每一个case里都要加

自定义View

@SuppressLint("NewApi")
public class SegmentControlView extends LinearLayout {

    private TextView textView1 = null;
    private TextView textView2 = null;
    private TextView textView3 = null;
    private View verTextView1 = null;//中间的竖线
    private View verTextView2 = null;//中间的竖线
    private onSegmentControlViewClickListener listener;

    public SegmentControlView(Context context) {
        super(context);
        initView();
    }

    public SegmentControlView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    public SegmentControlView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    private void initView() {

        textView1 = new TextView(getContext());
        textView2 = new TextView(getContext());
        textView3 = new TextView(getContext());
        verTextView1 = new View(getContext());
        verTextView2 = new View(getContext());

        textView1.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1));
        verTextView1.setLayoutParams(new LayoutParams(1, LayoutParams.MATCH_PARENT));
        textView2.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1));
        verTextView2.setLayoutParams(new LayoutParams(1, LayoutParams.MATCH_PARENT));
        textView3.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1));

        setSegmentText(0, getContext().getString(R.string.noti_msg));
        setSegmentText(1, getContext().getString(R.string.friends_list));
        setSegmentText(2, getContext().getString(R.string.all_list));
        setSegmentTextSize(16);//设置文字大小

        XmlPullParser xrp = getResources().getXml(R.drawable.seg_text_color_selector);
        try {
            ColorStateList csl = ColorStateList.createFromXml(getResources(), xrp);
            textView1.setTextColor(csl);
            textView2.setTextColor(csl);
            textView3.setTextColor(csl);
          } catch (Exception e) {
        }
        textView1.setGravity(Gravity.CENTER);
        textView2.setGravity(Gravity.CENTER);
        textView3.setGravity(Gravity.CENTER);
        textView1.setPadding(3, 6, 3, 6);
        textView2.setPadding(3, 6, 3, 6);
        textView3.setPadding(3, 6, 3, 6);
        textView1.setBackgroundResource(R.drawable.seg_left);
        textView2.setBackgroundResource(R.drawable.seg_middle);
        textView3.setBackgroundResource(R.drawable.seg_right);
        verTextView1.setBackgroundColor(getResources().getColor(R.color.blue));
        verTextView2.setBackgroundColor(getResources().getColor(R.color.blue));

        this.removeAllViews();
        this.addView(textView1);
        this.addView(verTextView1);
        this.addView(textView2);
        this.addView(verTextView2);
        this.addView(textView3);
        this.invalidate();

        textView1.setSelected(true);

        textView1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (textView1.isSelected()) {
                    return;
                }
                textView1.setSelected(true);
                textView2.setSelected(false);
                textView3.setSelected(false);
                if (listener != null) {
                    listener.onSegmentControlViewClick(textView1, 0);
                }
            }
        });
        textView2.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (textView2.isSelected()) {
                    return;
                }
                textView2.setSelected(true);
                textView1.setSelected(false);
                textView3.setSelected(false);
                if (listener != null) {
                    listener.onSegmentControlViewClick(textView2, 1);
                }
            }
        });

        textView3.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (textView3.isSelected()) {
                    return;
                }
                textView3.setSelected(true);
                textView1.setSelected(false);
                textView2.setSelected(false);
                if (listener != null) {
                    listener.onSegmentControlViewClick(textView2, 2);
                }
            }
        });
    }

    /**
     * 设置字体大小 单位dip
     * @param dp
     */
    public void setSegmentTextSize(int dp) {
        textView1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, dp);
        textView2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, dp);
        textView3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, dp);
    }

    /**
     * 设置文字
     * @param text
     * @param position
     */
    public void setSegmentText(int position, CharSequence text) {
        if (position == 0) {//左
            textView1.setText(text);
        }
        if (position == 1) {//中
            textView2.setText(text);
        }
        if (position == 2) {//右
            textView3.setText(text);
        }
    }

    public void setOnSegmentControlViewClickListener(onSegmentControlViewClickListener listener) {
        this.listener = listener;
    }

    public static interface onSegmentControlViewClickListener{

        /**
         * @param v
         * @param position 0-左边 1-中间 2-右边
         */
        public void onSegmentControlViewClick(View v,int position);
    }

    /**
     * dp与px转化函数
     * @param context
     * @param dp
     * @return
     */
    private static int dp2Px(Context context, float dp) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dp * scale + 0.5f);
    }
}

整体封装的还不错,需要修改UI的观众老爷可自行进行修改,大体功能已经实现了

3个Fragment中的一个

public class fragmenta extends Fragment{
    Button fragmentaButton;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        View view= inflater.inflate(R.layout.fragemnta, container, false);
        fragmentaButton=(Button)view.findViewById(R.id.fragmentaButtona);
        fragmentaButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Toast.makeText(getActivity(), "fragmenta", 1).show();
            }
        });
        return view;
    }

}

主布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.wjj.wjjdemo.MainActivity"
    android:background="@color/white">

    <com.wjj.wjjdemo.customView.SegmentControlView
        android:id="@+id/SegmentControlView"
        android:layout_width="240dp"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:background="@drawable/seg_linear"
        android:padding="0.5dp" >
    </com.wjj.wjjdemo.customView.SegmentControlView>

    <FrameLayout
        android:id="@+id/fragmentlayout"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_alignParentBottom="true"
        android:layout_below="@+id/SegmentControlView" >
    </FrameLayout>

</RelativeLayout>

这里要补充下,楼主在FrameLayout节点这一部分犯了一个错误,之前用Fragment来填充这一部分,导致出现了2个View重叠的问题,所以用FrameLayout之类的布局来填充就好了。

大体主要的代码就这些了,源码在下面会补上,布局文件资源文件什么的都在里面了,大家拿来就可以用。
http://yunpan.cn/cdcyxcXkLZnye 访问密码 0d8e
有疑问欢迎QQ联系452270579

时间: 2024-11-08 23:29:58

仿QQ电话/消息切换的自定义布局结合Fragment解决你的需求!的相关文章

C#仿QQ来消息提示

问题描述 如何实现 解决方案 解决方案二:http://www.google.com.hk/#hl=zh-CN&newwindow=1&safe=strict&q=C%23%E4%BB%BFQQ+%E6%B6%88%E6%81%AF%E6%8F%90%E7%A4%BA+&oq=C%23%E4%BB%BFQQ+%E6%B6%88%E6%81%AF%E6%8F%90%E7%A4%BA+&aq=f&aqi=&aql=&gs_sm=e&gs_

Android贝塞尔曲线初步学习第二课 仿QQ未读消息气泡拖拽黏连效果

上一节初步了解了Android端的贝塞尔曲线,这一节就举个栗子练习一下,仿QQ未读消息气泡,是最经典的练习贝塞尔曲线的东东,效果如下 附上github源码地址:https://github.com/MonkeyMushroom/DragBubbleView 欢迎star~ 大体思路就是画两个圆,一个黏连小球固定在一个点上,一个气泡小球跟随手指的滑动改变坐标.随着两个圆间距越来越大,黏连小球半径越来越小.当间距小于一定值,松开手指气泡小球会恢复原来位置:当间距超过一定值之后,黏连小球消失,气泡小球

Android自定义View 仿QQ侧滑菜单的实现代码

先看看QQ的侧滑效果 分析一下 先上原理图(不知道能否表达的清楚 ==) -首先这里使用了 Android 的HorizontalScrollView 水平滑动布局作为容器,当然我们需要继承它自定义一个侧滑视图 - 这个容器里面有一个父布局(一般用LinerLayout,本demo用的是),这个父布局里面有且只有两个子控件(布局),初始状态菜单页的位置在Y轴上存在偏移这样可以就可以形成主页叠在菜单页的上方的视觉效果:然后在滑动的过程程中 逐渐修正偏移,最后菜单页和主页并排排列.原理搞清了实现起来

Android 高仿QQ滑动弹出菜单标记已读、未读消息

  在上一篇博客<Android 高仿微信(QQ)滑动弹出编辑.删除菜单效果,增加下拉刷新功能>里,已经带着大家学习如何使用SwipeMenuListView这一开源库实现滑动列表弹出菜单,接下来,将进一步学习,如何为不同的list item呈现不同的菜单,此处我们做一个实例:Android 高仿QQ滑动弹出菜单标记已读.未读消息,看下效果图: 1. 创建项目,并导入SwipeMenuListView类库 2. 创建消息实体bean: public class Msg { public int

Android仿QQ滑动弹出菜单标记已读、未读消息_Android

在上一篇<Android仿微信滑动弹出编辑.删除菜单效果.增加下拉刷新功能>里,已经带着大家学习如何使用SwipeMenuListView这一开源库实现滑动列表弹出菜单,接下来,将进一步学习,如何为不同的list item呈现不同的菜单,此处我们做一个实例:Android 高仿QQ滑动弹出菜单标记已读.未读消息,看下效果图: 1. 创建项目,并导入SwipeMenuListView类库 2. 创建消息实体bean: public class Msg { public int id; publi

Android 仿QQ头像自定义截取功能_Android

看了Android版QQ的自定义头像功能,决定自己实现,随便熟悉下android绘制和图片处理这一块的知识. 先看看效果: 思路分析: 这个效果可以用两个View来完成,上层View是一个遮盖物,绘制半透明的颜色,中间挖了一个圆:下层的View用来显示图片,具备移动和缩放的功能,并且能截取某区域内的图片. 涉及到的知识点: 1.Matrix,图片的移动和缩放 2.Paint的setXfermode方法 3.图片放大移动后,截取一部分 编码实现: 自定义三个View: 1.下层View:ClipP

Android仿QQ滑动弹出菜单标记已读、未读消息

在上一篇<Android仿微信滑动弹出编辑.删除菜单效果.增加下拉刷新功能>里,已经带着大家学习如何使用SwipeMenuListView这一开源库实现滑动列表弹出菜单,接下来,将进一步学习,如何为不同的list item呈现不同的菜单,此处我们做一个实例:Android 高仿QQ滑动弹出菜单标记已读.未读消息,看下效果图: 1. 创建项目,并导入SwipeMenuListView类库 2. 创建消息实体bean: public class Msg { public int id; publi

Android 仿QQ头像自定义截取功能

看了Android版QQ的自定义头像功能,决定自己实现,随便熟悉下android绘制和图片处理这一块的知识. 先看看效果: 思路分析: 这个效果可以用两个View来完成,上层View是一个遮盖物,绘制半透明的颜色,中间挖了一个圆:下层的View用来显示图片,具备移动和缩放的功能,并且能截取某区域内的图片. 涉及到的知识点: 1.Matrix,图片的移动和缩放 2.Paint的setXfermode方法 3.图片放大移动后,截取一部分 编码实现: 自定义三个View: 1.下层View:ClipP

jquery仿QQ商城带左右按钮控制焦点图片切换滚动效果

jquery图片特效制作仿腾讯QQ商城首页banner焦点图片轮播切换效果,带索引按钮控制和左右按钮控制图片切换,实例代码如下,感兴趣的朋友可以参考下哈   复制代码 代码如下: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>jquery图片