Android 菜单

  在android中实现菜单功能有多种方法。
  Options Menu:用户按下menu Button时显示的菜单。
  Context Menu:用户长时间按下屏幕,所显示出来的菜单也称为上下文菜单。
  Submenu:子菜单。

  但是有时候这些内置的菜单并不能满足我们功能,这就需要自己自定义一种菜单。接下来我说的这种就是通过TabHost与RadioGroup结合完成的菜单。这也是很常用的一种底部菜单做法。

     <?xml version="1.0" encoding="UTF-8"?>
    <TabHost android:id="@android:id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <FrameLayout
    android:id="@android:id/tabcontent"
    android:layout_width="fill_parent"
    android:layout_height="0.0dip"
    android:layout_weight="1.0" />
    <TabWidget
    android:id="@android:id/tabs"
    android:visibility="gone"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="0.0" />
    <RadioGroup
    android:gravity="center_vertical"
    android:layout_gravity="bottom"
    android:orientation="horizontal"
    android:id="@+id/main_radio"
    android:background="@drawable/maintab_toolbar_bg"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <RadioButton
    android:id="@+id/radio_button0"
    android:tag="radio_button0"
    android:layout_marginTop="2.0dip"
    android:text="@string/alarm"
    android:drawableTop="@drawable/icon_1"
    style="@style/main_tab_bottom" />
    <RadioButton
    android:id="@+id/radio_button1"
    android:tag="radio_button1"
    android:layout_marginTop="2.0dip"
    android:text="@string/message"
    android:drawableTop="@drawable/icon_2"
    style="@style/main_tab_bottom" />
    <RadioButton
    android:id="@+id/radio_button2"
    android:tag="radio_button2"
    android:layout_marginTop="2.0dip"
    android:text="@string/photo"
    android:drawableTop="@drawable/icon_3"
    style="@style/main_tab_bottom" />
    <RadioButton
    android:id="@+id/radio_button3"
    android:tag="radio_button3"
    android:layout_marginTop="2.0dip"
    android:text="@string/music"
    android:drawableTop="@drawable/icon_4"
    style="@style/main_tab_bottom" />
    <RadioButton
    android:id="@+id/radio_button4"
    android:tag="radio_button4"
    android:layout_marginTop="2.0dip"
    android:text="@string/setting"
    android:drawableTop="@drawable/icon_5"
    style="@style/main_tab_bottom" />
    </RadioGroup>
    </LinearLayout>
    </TabHost>
     需要注意的是,如果用TabHost这个控件,其中有几个ID是必须这么写的,android:id="@android:id/tabhost   ;android:id="@android:id/tabcontent"; android:id="@android:id/tabs" ;之所以要这么写是因为在TabHost这个类中。需要实例化上述这个ID的控件。看源码:

       在TabActivity中有么个方法:

    @Override
    public void onContentChanged() {
    super.onContentChanged();
    mTabHost = (TabHost) findViewById(com.android.internal.R.id.tabhost);
    if (mTabHost == null) {
    throw new RuntimeException(
    "Your content must have a TabHost whose id attribute is " +
    "'android.R.id.tabhost'");
    }
    mTabHost.setup(getLocalActivityManager());
    }
    private void ensureTabHost() {
    if (mTabHost == null) {
    this.setContentView(com.android.internal.R.layout.tab_content);
    }
    }
当内容发生改变时它会调用这个方法,来更新列表或者其他视图,而这个方法中需要实例化TabHost,所以必须通过ID为tabhost实例化。
再看看TabHost这个类中
    public void setup() {
    mTabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
    if (mTabWidget == null) {
    throw new RuntimeException(
    "Your TabHost must have a TabWidget whose id attribute is 'android.R.id.tabs'");
    }


    // KeyListener to attach to all tabs. Detects non-navigation keys
    // and relays them to the tab content.
    mTabKeyListener = new OnKeyListener() {
    public boolean onKey(View v, int keyCode, KeyEvent event) {
    switch (keyCode) {
    case KeyEvent.KEYCODE_DPAD_CENTER:
    case KeyEvent.KEYCODE_DPAD_LEFT:
    case KeyEvent.KEYCODE_DPAD_RIGHT:
    case KeyEvent.KEYCODE_DPAD_UP:
    case KeyEvent.KEYCODE_DPAD_DOWN:
    case KeyEvent.KEYCODE_ENTER:
    return false;

    }
    mTabContent.requestFocus(View.FOCUS_FORWARD);
    return mTabContent.dispatchKeyEvent(event);
    }
    };
    mTabWidget.setTabSelectionListener(new TabWidget.OnTabSelectionChanged() {
    public void onTabSelectionChanged(int tabIndex, boolean clicked) {
    setCurrentTab(tabIndex);
    if (clicked) {
    mTabContent.requestFocus(View.FOCUS_FORWARD);
    }
    }
    });
    mTabContent = (FrameLayout) findViewById(com.android.internal.R.id.tabcontent);
    if (mTabContent == null) {
    throw new RuntimeException(
    "Your TabHost must have a FrameLayout whose id attribute is "
    + "'android.R.id.tabcontent'");
    }
    }
这个方法,是在增加选项卡之前由系统调用。在这个方法中需要通过tabs 这个ID实例化一个TabWidget,通过tabcontent这个ID实例化一个FrameLayout,用来放置选项卡内容。所以这两个ID也是固定的。
  在上述布局文件中隐藏了系统默认的Widget,取而代之的是带有图片的Button。
  看一下主要代码:
        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;


    public class MainActivity extends TabActivity implements OnCheckedChangeListener{
    /** Called when the activity is first created. */
    private TabHost mHost;
    private RadioGroup radioderGroup;


    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.maintabs);
    //实例化TabHost
    mHost=this.getTabHost();


    //添加选项卡
    mHost.addTab(mHost.newTabSpec("ONE").setIndicator("ONE")
    .setContent(new Intent(this,OneActivity.class)));
    mHost.addTab(mHost.newTabSpec("TWO").setIndicator("TWO")
    .setContent(new Intent(this,TwoActivity.class)));
    mHost.addTab(mHost.newTabSpec("THREE").setIndicator("THREE")
    .setContent(new Intent(this,ThreeActivity.class)));
    mHost.addTab(mHost.newTabSpec("FOUR").setIndicator("FOUR")
    .setContent(new Intent(this,FourActivity.class)));
    mHost.addTab(mHost.newTabSpec("FIVE").setIndicator("FIVE")
    .setContent(new Intent(this,FiveActivity.class)));
    radioderGroup = (RadioGroup) findViewById(R.id.main_radio);
    radioderGroup.setOnCheckedChangeListener(this);
    }


    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
    switch(checkedId){
    case R.id.radio_button0:
    mHost.setCurrentTabByTag("ONE");
    break;
    case R.id.radio_button1:
    mHost.setCurrentTabByTag("TWO");
    break;
    case R.id.radio_button2:
    mHost.setCurrentTabByTag("THREE");
    break;
    case R.id.radio_button3:
    mHost.setCurrentTabByTag("FOUR");
    break;
    case R.id.radio_button4:
    mHost.setCurrentTabByTag("FIVE");
    break;
    }
    }
    }

android进度条大致分为两种,水平进度条和圆形进度条。我们一般需要改的就是水平进度条,因为这个不是替换图片可以做到的,所以发下此教程。
首先,准备工作就是建立java运行环境,寻找一个顺手的反编译工具,这个不做过多赘述。具体请去谷歌一下。然后你需要复制出ROM自带的framework-res.apk,反编译之。
这时候进入正题,替换进度条需要修改两个xml文件,分别是:
framework-res.apk/res/drawable/progress_horizontal.xml (定义进度条颜色)                                   
framework-res.apk/res/value/styles.xml(定义进度条布局)


首先,progress_horizontal.xml 这里,你可以改的是进度条的边框弧度
<item android:id="@id/background">
<shape>
<corners android:radius="4.659973dip" />(半径自定义)


进度条的颜色
</corners>
<gradient
android:startColor="#FFFFFFFF"(颜色自定义)
android:endColor="#FFFFFFFF"(颜色自定义)
android:angle="270.0"
android:centerY="0.75"
android:centerColor="#FFFFFFFF"(颜色自定义)


<item android:id="@id/progress">
<clip>
<shape>
<corners android:radius="4.659973dip" />
<gradient
android:startColor="#ff61bbff"
android:endColor="#ff0091ff"
android:angle="270.0"
android:centerY="0.75"
android:centerColor="#ff32a7ff" />(这里的三个颜色定义为进度条背景)

做完了这些,你就完成了一半以上的工作了,因为这些颜色是配色原理,很难搞定。

接下来就是在styles.xml里布局了。


首先查找progressbar,找到这一行
    <style name="Widget.ProgressBar.Horizontal" parent="@style/Widget.ProgressBar">
        <item name="maxHeight">20.0dip</item>
        <item name="indeterminateOnly">false</item>
        <item name="indeterminateDrawable">@drawable/progress_indeterminate_horizontal</item>
        <item name="progressDrawable">@drawable/progress_horizontal</item>
        <item name="minHeight">20.0dip</item>
    </style>

将两个20.0dip改为10.0dip(这是我自己改的高度,各位可凭自己的喜好自行修改)。这里进度条的高度就搞定了。
这里还有一个问题就是,seekbar和progressbar的区别。
seekbar指的是拖动条,比如你打开设置,声音,音量的时候,看到的那个可以拖动的进度条。
所以紧随上一行代码之后,我们看到了下面的:
    <style name="Widget.SeekBar" parent="@style/Widget">
        <item name="focusable">true</item>
        <item name="maxHeight">20.0dip</item>
        <item name="indeterminateOnly">false</item>
        <item name="indeterminateDrawable">@drawable/progress_horizontal</item>
        <item name="progressDrawable">@drawable/progress_horizontal</item>
        <item name="minHeight">20.0dip</item>
        <item name="thumb">@drawable/seek_thumb</item>
        <item name="thumbOffset">8.0dip</item>


首先在布局文件中定义如下:
 

      <ProgressBar  
       android:id="@+id/loadProgressBar" 
       android:layout_width="fill_parent"  
       android:layout_height="wrap_content"  
       style="?android:attr/progressBarStyleHorizontal" 
       android:max="100" 
       android:progress="80" 
       android:progressDrawable="@drawable/progressbar" 
       /> 

 再在drawable目录下新增progressbar.xml文件,可以设置默认背景色和进度条的颜色(值得一提的是支持渐变色)
内容如下:
          <layer-listxmlns:android="http://schemas.android.com/apk/res/android"> 
     
   <itemandroid:id="@android:id/background"> 
       <shape> 
           <corners android:radius="5dip"/> 
           <gradient 
                   android:startColor="#ff9d9e9d" 
                   android:centerColor="#ff5a5d5a" 
                   android:centerY="0.75" 
                   android:endColor="#ff747674" 
                   android:angle="0" 
           /> 
       </shape> 
   </item> 
阅读更多
个人分类: Android
想对作者说点什么? 我来说一句

android 自定义菜单

2018年01月24日 16.63MB 下载

android 另类menu菜单提示

2011年09月09日 43KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭