首页 文章 精选 留言 我的

精选列表

搜索[移动解析],共10000篇文章
优秀的个人博客,低调大师

android移动视频会议系统开发

到新公司上班,接收的第一个项目是视频会议系统,基于AnyChat进行二次开发,在官网下载了demo了解后,发现缺少了一个发送文件功能,所以自己在原有的demo进行修改,增加了一个发送文件功能。 AnyChat具有缓冲区及文件传输功能,文件传输API接口:BRAC_TransFile,A、B两用户登录服务器成功之后,便可使用文件传输API接口传送文件,当A使用API接口:BRAC_TransFile向B发送文件时,B收到文件后,将触发B的回调函数:文件传输回调函数。 传送文件接口说明: int TransFile(int userid, String filepath, int wparam, int lparam,int flags, AnyChatOutParam outParam); 功能:传送文件给指定用户 返回值:0表示函数调用成功,否则为出错代码 参数: userid: 目标用户编号,只针对某一个用户,不能为-1(所有人) filepath: 本地文件名,含路径 wParam: 附带参数1,便于上层应用扩展 lParam: 附带参数2 dwFlags: 特殊功能标志,参考:“TransBufferEx”方法 outParam: 若函数调用成功,则内核通过该参数输出任务ID 在使用中,附带参数以及特殊功能标识是保留参数,不需要用到,赋值为0就可以了。一开始在设置outParam参数时设置为null,程序发生异常,查阅官方文档后发现,当函数调用成功,内核会通过outParam的SetIntValue方法设置任务ID(TaskId)。 B用户要实现接收文件传输回调函数需要做两个工作。 1、在需要接收的类实现AnyChatTransDataEvent接口 2、设置回调接收函数SetTransDataEvent (注:AnyChatTransDataEvent和SetTransDataEvent是由AnyChat提供的api) 文件传输回调函数说明: public voidOnAnyChatTransFile(int dwUserid, String FileName,String TempFilePath, int dwFileLength, int wParam, int lParam, int dwTaskId); 参数: dwUserid: 用户ID,指示发送用户 FileName: 文件名(含扩展名,不含路径) TempFilePath: 接收完成后,SDK保存在本地的临时文件(包含完整路径) dwFileLength: 文件总长度 wParam: lParam: dwTaskId: 该文件所对应的任务编号 主要代码如下,注释的也比较清楚。详细的可参考《AnyChat for Android SDK开发手册》。(AnyChat for Android SDK:http://www.anychat.cn/download.html) RoomActivity.java 在传输过程中还可以通过QueryTransTaskInfo接口查询传输任务相关信息,需要传人用户id以及任务id等参数。 查询传输任务相关信息接口说明: INT QueryTransTaskInfo(INT Userid, INT TaskId,int infoname, AnyChatOutParam outParam); 功能:查询与传输任务相关的信息,如传输进度、传输状态、传输码率等 返回值:0表示查询成功,否则为出错代码 参数: dwUserid:任务发起者用户编号(并非传输目标用户编号) dwTaskId:需要查询的任务编号 infoname需要查询的信息代码(见备注附表) outParam:若函数调用成功,则内核通过该参数输出查询结果 anychat.QueryTransTaskInfo(dwUserId,taskId,AnyChatDefine.BRAC_TRANSTASK_STATUS, outParam); AnyChatDefine.BRAC_TRANSTASK_STATUS是一个常量值为3,用于查询任务当前状态,通过outParam.GetIntValue()取得任务状态值,2为传输状态,3为完成状态. 本文转自 fanxiaojun51CTO博客,原文链接:http://blog.51cto.com/2343338/1578955,如需转载请自行联系原作者

优秀的个人博客,低调大师

【移动开发】Android中的底部菜单框架(Fragment)

今天,我将总结一下Android应用中大家经常见到的底部导航栏的几种实现! 一。TabHost + RadioGroup实现方式 在我们平时开发过程中使用的TabHost是在上方,这里我们简单修改了一下<TabHost>的布局,让叶片放到了底部。 main.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 <?xml version= "1.0" encoding= "utf-8" ?> <TabHost xmlns:android= "http://schemas.android.com/apk/res/android" android:id= "@android:id/tabhost" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "horizontal" > <LinearLayout android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "vertical" > <TabWidget android:id= "@android:id/tabs" android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:visibility= "gone" /> <FrameLayout android:id= "@android:id/tabcontent" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:layout_weight= "1.0" /> <RadioGroup android:id= "@+id/radioGroup" android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:layout_gravity= "bottom" android:background= "@drawable/bar" android:gravity= "center_vertical" android:orientation= "horizontal" > <RadioButton android:id= "@+id/rd_home" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/home_icon" android:text= "主页" /> <RadioButton android:id= "@+id/rd_wt" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/wb_icon_write_n" android:text= "发表" /> <RadioButton android:id= "@+id/rd_msg" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/msg_icon" android:text= "信息" /> <RadioButton android:id= "@+id/rd_more" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/more_icon" android:text= "更多" /> </RadioGroup> </LinearLayout> </TabHost> styles.xml 1 2 3 4 5 6 7 8 9 <style name= "main_btn_style" > <item name= "android:button" >@ null </item> <item name= "android:textSize" >10dp</item> <item name= "android:textColor" >#ffffff</item> <item name= "android:gravity" >center_horizontal</item> <item name= "android:drawablePadding" >4dp</item> <item name= "android:layout_weight" > 1.0 </item> <item name= "android:background" >@drawable/main_btn_bg_d</item> </style> main_btn_bg_d.xml 1 2 3 4 5 <?xml version= "1.0" encoding= "utf-8" ?> <selector xmlns:android= "http://schemas.android.com/apk/res/android" > <item android:drawable= "@drawable/main_btn_bg" android:state_enabled= "true" android:state_pressed= "true" ></item> <item android:drawable= "@drawable/main_btn_bg" android:state_checked= "true" android:state_enabled= "true" ></item> </selector> 这里需要注意的是: 1.main.xml中:TabWidget的id必须是@android:id/tabs,FrameLayout的id必须是 @android:id/tabcontent。 2.把TabWidget的Visibility设置成了gone!也就是默认难看的风格不见了:,取而代之的是5个带风格的单选按钮. MainActivity类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package com.zhf.android_tabhost; import android.app.TabActivity; import android.content.Intent; import android.os.Bundle; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; import android.widget.TabHost; import android.widget.TabHost.TabSpec; public class MainActivity extends TabActivity { private TabHost tabHost; @Override public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.main); tabHost = this .getTabHost(); TabSpec homeSpec = tabHost.newTabSpec( "home" ).setIndicator( "home" ).setContent( new Intent( this ,HomeActivity. class )); TabSpec writeSpec = tabHost.newTabSpec( "write" ).setIndicator( "write" ).setContent( new Intent( this ,WriteActivity. class )); TabSpec msgSpec = tabHost.newTabSpec( "msg" ).setIndicator( "msg" ).setContent( new Intent( this ,MsgActivity. class )); TabSpec moreSpec = tabHost.newTabSpec( "more" ).setIndicator( "more" ).setContent( new Intent( this ,MoreActivity. class )); tabHost.addTab(homeSpec); tabHost.addTab(writeSpec); tabHost.addTab(msgSpec); tabHost.addTab(moreSpec); RadioGroup rg = (RadioGroup) this .findViewById(R.id.radioGroup); rg.setOnCheckedChangeListener( new OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { switch (checkedId) { case R.id.rd_home: tabHost.setCurrentTabByTag( "home" ); break ; case R.id.rd_wt: tabHost.setCurrentTabByTag( "write" ); break ; case R.id.rd_msg: tabHost.setCurrentTabByTag( "msg" ); break ; case R.id.rd_more: tabHost.setCurrentTabByTag( "more" ); break ; default : break ; } } }); } } 注: 1.由于TabWidget被隐藏,所以相关的事件也会无效,这里取巧用RadioGroup与RadioButton的特性来处理切换,然后监听事件调用setCurrentTabByTag来切换Activity。 2.注意即使TabWidget被隐藏,也要为其设置indicator,否则会保持。 效果图: (点击底部就可以实现切换不同的Activity的操作了,这里需要注意的一点是,切换底部菜单时不会重新调用onCreate()方法的!!) 二.底部回调接口实现(使用Fragment)--- 重要! 这种方式使用了最新的Fragment,采用了底部导航栏回调接口的方法,来切换底部菜单,并且每次切换回重新调用onCreate()方法!! main.xml: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <?xml version= "1.0" encoding= "utf-8" ?> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http://schemas.android.com/tools" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "vertical" tools:context= ".MainActivity" > <LinearLayout android:layout_width= "fill_parent" android:layout_height= "0dp" android:layout_weight= "10" android:orientation= "vertical" > <RelativeLayout android:id= "@+id/main_title_RelativeLayout" android:layout_width= "fill_parent" android:layout_height= "50dp" android:background= "@drawable/fragment_bottom_normal" android:orientation= "horizontal" > <TextView android:id= "@+id/main_title_TextView" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:layout_centerInParent= "true" android:text= "主页" android:textColor= "@android:color/white" android:textSize= "24sp" /> </RelativeLayout> <FrameLayout android:id= "@+id/main_detail_FrameLayout" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:background= "#ffffff" > </FrameLayout> </LinearLayout> <fragment android:id= "@+id/bottom_fragment" android:name= "com.zhf.frameworkdemo02.fragments.BottomFragment" android:layout_width= "fill_parent" android:layout_height= "0dp" android:layout_weight= "1" /> </LinearLayout> 这里由于我们底部菜单我们采用了fragment,所以布局里面要留出位置! BottomFragment类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 package com.zhf.frameworkdemo02.fragments; import com.zhf.frameworkdemo02.R; import android.app.Activity; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; /** * 页面底部导航栏 * * @author ZHF * */ public class BottomFragment extends Fragment { //默认回调接口实现类的对象 private Callbacks callbacks = defaultCallbacks; /** Fragment和Activity建立关联的时候调用 **/ @Override public void onAttach(Activity activity) { super .onAttach(activity); //当前类是否实现了底部导航栏点击事件回调接口 if (!(activity instanceof Callbacks)) { throw new IllegalStateException( "Activity must implements fragment's callbacks !" ); } callbacks = (Callbacks) activity; } /** 为Fragment加载布局时调用 **/ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { RadioGroup radioGroup = (RadioGroup) inflater.inflate(R.layout.fragment_bottom, container, false ); //绑定监听器 radioGroup.setOnCheckedChangeListener(changeListener); return radioGroup; } /**RadioGroup监听器**/ private OnCheckedChangeListener changeListener = new OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { System.out.println(checkedId); callbacks.onItemSelected(checkedId); //调用接口中方法 } }; public interface Callbacks{ /**导航栏回调接口**/ public void onItemSelected( int item); } /**默认回调实现类的对象**/ private static Callbacks defaultCallbacks = new Callbacks() { @Override public void onItemSelected( int item) { //什么都不干 } }; /**Fragment和Activity解除关联的时候调用**/ @Override public void onDetach() { super .onDetach(); callbacks = defaultCallbacks; } } 底部菜单布局fragment_bottom.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 <?xml version= "1.0" encoding= "utf-8" ?> <RadioGroup xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "horizontal" > <RadioButton android:id= "@+id/fragment_bottom_home" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:layout_weight= "1" android:background= "@drawable/fragment_bottom_selector" android:button= "@null" android:drawableTop= "@drawable/main_readiobutton_home" android:gravity= "center" android:text= "@string/home" android:textColor= "@color/white" android:textSize= "12sp" /> <View android:layout_width= "1dp" android:layout_height= "fill_parent" android:background= "@color/white" /> <RadioButton android:id= "@+id/fragment_bottom_order" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:layout_weight= "1" android:background= "@drawable/fragment_bottom_selector" android:button= "@null" android:drawableTop= "@drawable/main_readiobutton_order" android:gravity= "center" android:text= "@string/order" android:textColor= "@color/white" android:textSize= "12sp" /> <View android:layout_width= "1dp" android:layout_height= "fill_parent" android:background= "@color/white" /> <RadioButton android:id= "@+id/fragment_bottom_notice" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:layout_weight= "1" android:background= "@drawable/fragment_bottom_selector" android:button= "@null" android:drawableTop= "@drawable/main_readiobutton_notice" android:gravity= "center" android:text= "@string/notice" android:textColor= "@color/white" android:textSize= "12sp" /> <View android:layout_width= "1dp" android:layout_height= "fill_parent" android:background= "@color/white" /> <RadioButton android:id= "@+id/fragment_bottom_more" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:layout_weight= "1" android:background= "@drawable/fragment_bottom_selector" android:button= "@null" android:drawablePadding= "3dip" android:drawableTop= "@drawable/main_readiobutton_more" android:gravity= "center" android:text= "@string/more" android:textColor= "@color/white" android:textSize= "12sp" /> </RadioGroup> 这里我们定义了一个框架类:GeneralFragment(所有的fragment界面都需继承它) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 package com.zhf.frameworkdemo02.fragments; import java.io.Serializable; import com.zhf.frameworkdemo02.R; import com.zhf.frameworkdemo02.view.OrderView; import com.zhf.frameworkdemo02.view.HomeView; import com.zhf.frameworkdemo02.view.MoreView; import com.zhf.frameworkdemo02.view.NoticeView; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; /** * 框架类,抽象公共方法 * @author ZHF * */ public class GeneralFragment extends Fragment implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private int item; //用于区分底部菜单项 protected static View main_title_RelativeLayout; //标题栏 protected final static String key = "Bundle" ; //跳转值传递key的名称 @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super .onCreate(savedInstanceState); if (getArguments() != null ) { //根据接收子类传来的arguments判断item的哪一项 if (getArguments().containsKey(MainFragment.Item)) { item = getArguments().getInt(MainFragment.Item); } } } /**为Fragment加载布局时调用 **/ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_general, container, false ); GeneralFragment fragment = null ; switch (item) { case R.id.fragment_bottom_home: //初始化主页 fragment = new HomeView(); break ; case R.id.fragment_bottom_order: fragment = new OrderView(); //初始化订单 break ; case R.id.fragment_bottom_notice: fragment = new NoticeView(); //初始化公告 break ; case R.id.fragment_bottom_more: fragment = new MoreView(); //初始化更多 break ; default : break ; } if (fragment != null ) { //更换mainView中间的内容(home,msg,at,more) getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.general_fragment, fragment).commit(); } main_title_RelativeLayout = ((View) container.getParent()).findViewById(R.id.main_title_RelativeLayout); //将生成的view返回 return view; } /**设置标题**/ protected void setTitle(Object title) { if (main_title_RelativeLayout != null ) { //标题栏中的文字 TextView mTvTitle = (TextView) main_title_RelativeLayout.findViewById(R.id.main_title_TextView); if (mTvTitle != null ) { if (title instanceof Integer) { //整型 mTvTitle.setText((Integer)title); } else { //字符类型 mTvTitle.setText((CharSequence)title); } } } } /**页面跳转值传递**/ protected void setBundle(Object... objects) { Bundle arguments = new Bundle(); arguments.putSerializable(key, objects); GeneralFragment generalFragment = new GeneralFragment(); generalFragment.setArguments(arguments); } /**获取所传递的值**/ protected Object[] getBundle() { if (getArguments() != null ) { System.out.println( "getBundle" ); if (getArguments().containsKey(key)) { Object[] object = (Object[]) getArguments().getSerializable(key); return object; } } return null ; } /**无参页面跳转**/ protected void toIntent(GeneralFragment generalFragment) { if (generalFragment != null ) { getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.general_fragment, generalFragment).commit(); } } } 程序入口MainFragment: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package com.zhf.frameworkdemo02.fragments; import com.zhf.frameworkdemo02.R; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; /** *MainView * @author ZHF * */ public class MainFragment extends FragmentActivity implements BottomFragment.Callbacks { public final static String Item = "item" ; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super .onCreate(savedInstanceState); setContentView(R.layout.main); //初始化默认调用接口中item选中方法 onItemSelected(R.id.fragment_bottom_home); } @Override public void onItemSelected( int item) { Bundle arguments = new Bundle(); arguments.putInt(Item, item); //将选中的底部radio的Id放进去 GeneralFragment generalFragment = new GeneralFragment(); generalFragment.setArguments(arguments); //设置参数值 //这里根据item的ID进行界面跳转 FragmentManager fm = getSupportFragmentManager(); fm.beginTransaction().replace(R.id.main_detail_FrameLayout, generalFragment).commit(); } } 说明:这里我们的每个界面都将采用Fragment,故每个界面需重写onCreateView() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.zhf.frameworkdemo02.view; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.zhf.frameworkdemo02.R; import com.zhf.frameworkdemo02.fragments.GeneralFragment; /** * 主页面 * @author ZHF * */ public class HomeView extends GeneralFragment{ @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super .onCreate(savedInstanceState); super .setTitle( "主页" ); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.home, container, false ); } } (其他三个略) 最终效果图: ok!大功告成!相当实用的!有兴趣的可以学习一下! 源码下载:http://down.51cto.com/data/1009354 今天,我将总结一下Android应用中大家经常见到的底部导航栏的几种实现! 一。TabHost + RadioGroup实现方式 在我们平时开发过程中使用的TabHost是在上方,这里我们简单修改了一下<TabHost>的布局,让叶片放到了底部。 main.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 <?xml version= "1.0" encoding= "utf-8" ?> <TabHost xmlns:android= "http://schemas.android.com/apk/res/android" android:id= "@android:id/tabhost" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "horizontal" > <LinearLayout android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "vertical" > <TabWidget android:id= "@android:id/tabs" android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:visibility= "gone" /> <FrameLayout android:id= "@android:id/tabcontent" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:layout_weight= "1.0" /> <RadioGroup android:id= "@+id/radioGroup" android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:layout_gravity= "bottom" android:background= "@drawable/bar" android:gravity= "center_vertical" android:orientation= "horizontal" > <RadioButton android:id= "@+id/rd_home" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/home_icon" android:text= "主页" /> <RadioButton android:id= "@+id/rd_wt" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/wb_icon_write_n" android:text= "发表" /> <RadioButton android:id= "@+id/rd_msg" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/msg_icon" android:text= "信息" /> <RadioButton android:id= "@+id/rd_more" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/more_icon" android:text= "更多" /> </RadioGroup> </LinearLayout> </TabHost> styles.xml 1 2 3 4 5 6 7 8 9 <style name= "main_btn_style" > <item name= "android:button" >@ null </item> <item name= "android:textSize" >10dp</item> <item name= "android:textColor" >#ffffff</item> <item name= "android:gravity" >center_horizontal</item> <item name= "android:drawablePadding" >4dp</item> <item name= "android:layout_weight" > 1.0 </item> <item name= "android:background" >@drawable/main_btn_bg_d</item> </style> main_btn_bg_d.xml 1 2 3 4 5 <?xml version= "1.0" encoding= "utf-8" ?> <selector xmlns:android= "http://schemas.android.com/apk/res/android" > <item android:drawable= "@drawable/main_btn_bg" android:state_enabled= "true" android:state_pressed= "true" ></item> <item android:drawable= "@drawable/main_btn_bg" android:state_checked= "true" android:state_enabled= "true" ></item> </selector> 这里需要注意的是: 1.main.xml中:TabWidget的id必须是@android:id/tabs,FrameLayout的id必须是 @android:id/tabcontent。 2.把TabWidget的Visibility设置成了gone!也就是默认难看的风格不见了:,取而代之的是5个带风格的单选按钮. MainActivity类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package com.zhf.android_tabhost; import android.app.TabActivity; import android.content.Intent; import android.os.Bundle; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; import android.widget.TabHost; import android.widget.TabHost.TabSpec; public class MainActivity extends TabActivity { private TabHost tabHost; @Override public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.main); tabHost = this .getTabHost(); TabSpec homeSpec = tabHost.newTabSpec( "home" ).setIndicator( "home" ).setContent( new Intent( this ,HomeActivity. class )); TabSpec writeSpec = tabHost.newTabSpec( "write" ).setIndicator( "write" ).setContent( new Intent( this ,WriteActivity. class )); TabSpec msgSpec = tabHost.newTabSpec( "msg" ).setIndicator( "msg" ).setContent( new Intent( this ,MsgActivity. class )); TabSpec moreSpec = tabHost.newTabSpec( "more" ).setIndicator( "more" ).setContent( new Intent( this ,MoreActivity. class )); tabHost.addTab(homeSpec); tabHost.addTab(writeSpec); tabHost.addTab(msgSpec); tabHost.addTab(moreSpec); RadioGroup rg = (RadioGroup) this .findViewById(R.id.radioGroup); rg.setOnCheckedChangeListener( new OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { switch (checkedId) { case R.id.rd_home: tabHost.setCurrentTabByTag( "home" ); break ; case R.id.rd_wt: tabHost.setCurrentTabByTag( "write" ); break ; case R.id.rd_msg: tabHost.setCurrentTabByTag( "msg" ); break ; case R.id.rd_more: tabHost.setCurrentTabByTag( "more" ); break ; default : break ; } } }); } } 注: 1.由于TabWidget被隐藏,所以相关的事件也会无效,这里取巧用RadioGroup与RadioButton的特性来处理切换,然后监听事件调用setCurrentTabByTag来切换Activity。 2.注意即使TabWidget被隐藏,也要为其设置indicator,否则会保持。 效果图: (点击底部就可以实现切换不同的Activity的操作了,这里需要注意的一点是,切换底部菜单时不会重新调用onCreate()方法的!!) 二.底部回调接口实现(使用Fragment)--- 重要! 这种方式使用了最新的Fragment,采用了底部导航栏回调接口的方法,来切换底部菜单,并且每次切换回重新调用onCreate()方法!! main.xml: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <?xml version= "1.0" encoding= "utf-8" ?> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http://schemas.android.com/tools" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "vertical" tools:context= ".MainActivity" > <LinearLayout android:layout_width= "fill_parent" android:layout_height= "0dp" android:layout_weight= "10" android:orientation= "vertical" > <RelativeLayout android:id= "@+id/main_title_RelativeLayout" android:layout_width= "fill_parent" android:layout_height= "50dp" android:background= "@drawable/fragment_bottom_normal" android:orientation= "horizontal" > <TextView android:id= "@+id/main_title_TextView" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:layout_centerInParent= "true" android:text= "主页" android:textColor= "@android:color/white" android:textSize= "24sp" /> </RelativeLayout> <FrameLayout android:id= "@+id/main_detail_FrameLayout" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:background= "#ffffff" > </FrameLayout> </LinearLayout> <fragment android:id= "@+id/bottom_fragment" android:name= "com.zhf.frameworkdemo02.fragments.BottomFragment" android:layout_width= "fill_parent" android:layout_height= "0dp" android:layout_weight= "1" /> </LinearLayout> 这里由于我们底部菜单我们采用了fragment,所以布局里面要留出位置! BottomFragment类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 package com.zhf.frameworkdemo02.fragments; import com.zhf.frameworkdemo02.R; import android.app.Activity; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; /** * 页面底部导航栏 * * @author ZHF * */ public class BottomFragment extends Fragment { //默认回调接口实现类的对象 private Callbacks callbacks = defaultCallbacks; /** Fragment和Activity建立关联的时候调用 **/ @Override public void onAttach(Activity activity) { super .onAttach(activity); //当前类是否实现了底部导航栏点击事件回调接口 if (!(activity instanceof Callbacks)) { throw new IllegalStateException( "Activity must implements fragment's callbacks !" ); } callbacks = (Callbacks) activity; } /** 为Fragment加载布局时调用 **/ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { RadioGroup radioGroup = (RadioGroup) inflater.inflate(R.layout.fragment_bottom, container, false ); //绑定监听器 radioGroup.setOnCheckedChangeListener(changeListener); return radioGroup; }

优秀的个人博客,低调大师

【移动开发】Android中Theme和Style的使用

当我们做项目到一定程度的时候,Android提供给我们的简单的UI控件(虽然后期ADT插件更新中增加了不少)已经不能满足我们的需要,一款成功的软件不仅要功能强大,漂亮的界面同样会吸引不少用户! 这里,我将总结一下Android提供给我们的两个重要的资源:Theme 和 Style。 1.Theme(是针对窗体级别的,可以改变窗体样式) 官方文档 Themes are Android's mechanism for applying a consistent style to an app or activity. The style specifies the visual properties of the elements that make up your user interface, such as color, height, padding and font size. To promote greater cohesion between all apps on the platform, Android provides three system themes that you can choose from when building apps for Ice Cream Sandwich: 主题是Android的机制被应用一个相同风格的应用程序或Activity中。样式指定了视觉属性的元素装饰你的用户界面,如颜色、高度、填充和字体大小。促进更大的凝聚力在所有平台的应用程序,Android提供了三个系统的主题,您可以选择在构建应用程序选择不同的主题: Holo Light Holo Dark Holo Light with dark action bars 官方图: 1.1.使用 Android系统的themes.xml和style.xml(位于/base/core/res/res/values/)包含了很多系统定义好的style,建议在里面挑个合适的,然后再继承修改。以下属性是在Themes中比较常见的,源自Android系统本身的themes.xml: 1 2 3 4 5 6 7 8 < style name = "simple_dialog" parent = "@android:style/Theme.Dialog" > < item name = "android:windowFrame" >@null</ item > <!-- Dialog的WindowFrame框为无 --> < item name = "android:windowNoTitle" >true</ item > < item name = "android:windowIsFloating" >true</ item > <!-- 是否悬浮在activity上 --> < item name = "android:windowIsTranslucent" >true</ item > <!-- 是否半透明 --> < item name = "android:backgroundDimEnabled" >false</ item > <!-- 背景是否模糊 --> </ style > 有人会问从哪里学习这些主题?其实系统就自带了很多,看下图: 在AndroidManifest的Application中,点击Theme选项,系统资源里就有相当多的主题供你选择。 A.应用到Application 1 <application android:theme= "@style/CustomTheme" > B.应用到Activity 1 <activity android:theme= "@android:style/Theme.Dialog" > 2.Style(是针对窗体元素级别的,改变指定控件或者Layout的样式) 官方文档: A style is a collection of properties that specify the look and format for a View or window. A style can specify properties such as height, padding, font color, font size, background color, and much more. A style is defined in an XML resource that is separate from the XML that specifies the layout. 风格是一个集合的属性用于指定具有一定外观和格式的视图或窗口。一个风格可以指定属性如高度、填充、字体颜色、字体大小、背景色等等。一个样式定义在XML资源,独立于XML指定布局。 Styles in Android share a similar philosophy to cascading stylesheets in web design—they allow you to separate the design from the content. 风格在安卓中的份额就如同级联样式表在web设计中的设计,允许你将内容分割开来设计 2.1简单使用 一个简单地样式 1 2 3 4 5 6 < TextView android:layout_width = "fill_parent" android:layout_height = "wrap_content" android:textColor = "#00FF00" android:typeface = "monospace" android:text = "@string/hello" /> 可以在任何相同的地方被引用 1 2 3 <TextView style= "@style/CodeFont" android:text= "@string/hello" /> 2.2定义风格 首先可以在res/values/下创建一个xml,用于定义style(注意:根结点必须是<resources>) 1 2 3 4 5 6 7 8 9 <? xml version = "1.0" encoding = "utf-8" ?> < resources > < style name = "CodeFont" parent = "@android:style/TextAppearance.Medium" > < item name = "android:layout_width" >fill_parent</ item > < item name = "android:layout_height" >wrap_content</ item > < item name = "android:textColor" >#00FF00</ item > < item name = "android:typeface" >monospace</ item > </ style > </ resources > 这里我们可以看到,该style的名称为CodeFont,parent后面是父类的style,(当然,我们也可以不用继承父类style),接下来每一个item定义一个属性。定义属性的最好方法就是在api文档里找到这个view的xml属性,比如在EditText中有InputType这个属性,那么在你的style里面你就可以来定义它。 ok! 就是这些了! 本文转自zhf651555765 51CTO博客,原文链接:http://blog.51cto.com/smallwoniu/1251507 ,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册