update menu
|
After Width: | Height: | Size: 173 B |
|
After Width: | Height: | Size: 191 B |
|
After Width: | Height: | Size: 154 B |
|
After Width: | Height: | Size: 159 B |
|
After Width: | Height: | Size: 189 B |
|
After Width: | Height: | Size: 165 B |
|
After Width: | Height: | Size: 171 B |
|
After Width: | Height: | Size: 151 B |
|
After Width: | Height: | Size: 158 B |
|
After Width: | Height: | Size: 172 B |
|
After Width: | Height: | Size: 179 B |
|
After Width: | Height: | Size: 203 B |
|
After Width: | Height: | Size: 158 B |
|
After Width: | Height: | Size: 163 B |
|
After Width: | Height: | Size: 190 B |
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2010 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<transition xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/md__list_pressed_holo_dark" />
|
||||
<item android:drawable="@drawable/md__list_longpressed_holo" />
|
||||
</transition>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2010 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:state_window_focused="false" android:drawable="@color/md__transparent" />
|
||||
|
||||
<!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
|
||||
<item android:state_focused="true" android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/md__list_selector_disabled_holo_dark" />
|
||||
<item android:state_focused="true" android:state_enabled="false" android:drawable="@drawable/md__list_selector_disabled_holo_dark" />
|
||||
<item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/md__list_selector_background_transition_holo_dark" />
|
||||
<item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/md__list_selector_background_transition_holo_dark" />
|
||||
<item android:state_focused="true" android:drawable="@drawable/md__list_focused_holo" />
|
||||
</selector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/MenuDrawer.Widget.Category" />
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/MenuDrawer.Widget.Title" />
|
||||
@@ -22,5 +22,7 @@
|
||||
<color name="grey1">#646464</color>
|
||||
<color name="grey2">#c8c8c8</color>
|
||||
<color name="grey3">#323232</color>
|
||||
<color name="md__transparent">#00000000</color>
|
||||
<color name="md__defaultBackground">#FF555555</color>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,28 @@
|
||||
<resources>
|
||||
|
||||
<!-- ID used when defining the content layout in XML. -->
|
||||
<item name="mdContent" type="id"/>
|
||||
|
||||
<!-- ID used when defining the menu layout in XML. -->
|
||||
<item name="mdMenu" type="id"/>
|
||||
|
||||
<!-- The ID of the content container. -->
|
||||
<item name="md__content" type="id"/>
|
||||
|
||||
<!-- The ID of the menu container. -->
|
||||
<item name="md__menu" type="id"/>
|
||||
|
||||
<!-- The ID of the drawer. -->
|
||||
<item name="md__drawer" type="id"/>
|
||||
|
||||
<!-- Used with View#setTag(int) to specify a position for the active view. -->
|
||||
<item name="mdActiveViewPosition" type="id"/>
|
||||
<item name="mdItem" type="id"/>
|
||||
|
||||
<item name="md__translationX" type="id"/>
|
||||
|
||||
<item name="md__translationY" type="id"/>
|
||||
|
||||
|
||||
|
||||
</resources>
|
||||
@@ -29,5 +29,36 @@
|
||||
<item name="switchStyle">@style/Widget.Holo.Light.CompoundButton.Switch</item>
|
||||
</style>
|
||||
|
||||
<style name="MenuDrawer"/>
|
||||
|
||||
<style name="MenuDrawer.Widget"/>
|
||||
|
||||
<style name="MenuDrawer.Widget.Category">
|
||||
<item name="android:textStyle">bold</item>
|
||||
<item name="android:textColor">?android:attr/textColorSecondaryInverse</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:textAllCaps">true</item>
|
||||
|
||||
<item name="android:gravity">center_vertical</item>
|
||||
<item name="android:paddingLeft">16dp</item>
|
||||
<item name="android:background">@drawable/md__category_background</item>
|
||||
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:ellipsize">end</item>
|
||||
</style>
|
||||
|
||||
<style name="MenuDrawer.Widget.Title">
|
||||
<item name="android:background">@drawable/md__list_selector_holo_dark</item>
|
||||
<item name="android:textAppearance">?android:attr/textAppearance</item>
|
||||
<item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
|
||||
<item name="android:textSize">18sp</item>
|
||||
<item name="android:paddingLeft">16dp</item>
|
||||
<item name="android:paddingRight">32dp</item>
|
||||
<item name="android:paddingTop">8dp</item>
|
||||
<item name="android:paddingBottom">8dp</item>
|
||||
<item name="android:drawablePadding">16dp</item>
|
||||
<item name="android:gravity">center_vertical</item>
|
||||
</style>
|
||||
|
||||
|
||||
</resources>
|
||||
@@ -46,7 +46,7 @@ import android.os._
|
||||
import android.preference.{Preference, PreferenceManager}
|
||||
import android.util.Log
|
||||
import android.view.{ViewGroup, Gravity, ViewParent, KeyEvent}
|
||||
import android.widget.{LinearLayout, CompoundButton, RelativeLayout, TextView}
|
||||
import android.widget._
|
||||
import com.actionbarsherlock.view.Menu
|
||||
import com.actionbarsherlock.view.MenuItem
|
||||
import com.google.analytics.tracking.android.EasyTracker
|
||||
@@ -68,7 +68,11 @@ import scala.concurrent.ops._
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
||||
import com.google.ads.{AdRequest, AdSize, AdView}
|
||||
import net.simonvt.menudrawer.MenuDrawer
|
||||
import javax.swing.text.html.ListView
|
||||
|
||||
import com.github.shadowsocks.database.{MenuAdapter, Item, Category}
|
||||
import scala.collection.mutable.ListBuffer
|
||||
import com.github.shadowsocks.database.Category
|
||||
import com.github.shadowsocks.database.Item
|
||||
|
||||
object Shadowsocks {
|
||||
|
||||
@@ -222,6 +226,8 @@ class Shadowsocks
|
||||
lazy val status = getSharedPreferences(Key.status, Context.MODE_PRIVATE)
|
||||
lazy val receiver = new StateBroadcastReceiver
|
||||
lazy val drawer = MenuDrawer.attach(this)
|
||||
lazy val listView = new ListView(this)
|
||||
lazy val menuAdapter = new MenuAdapter(this, getMenuList)
|
||||
|
||||
private val handler: Handler = new Handler {
|
||||
override def handleMessage(msg: Message) {
|
||||
@@ -399,11 +405,8 @@ class Shadowsocks
|
||||
setHeaderRes(R.xml.shadowsocks_headers)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val menuView = new TextView(this)
|
||||
menuView.setTextColor(0xFFFFFFFF)
|
||||
menuView.setText("As the drawer opens, the drawer indicator icon becomes smaller.")
|
||||
menuView.setGravity(Gravity.CENTER)
|
||||
drawer.setMenuView(menuView)
|
||||
listView.setAdapter(menuAdapter)
|
||||
drawer.setMenuView(listView)
|
||||
|
||||
// The drawable that replaces the up indicator in the action bar
|
||||
drawer.setSlideDrawable(R.drawable.ic_drawer)
|
||||
@@ -440,26 +443,44 @@ class Shadowsocks
|
||||
handler.sendEmptyMessage(MSG_INITIAL_FINISH)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* override def onCreateOptionsMenu(menu: Menu): Boolean = {
|
||||
val isRoot = status.getBoolean(Key.isRoot, false)
|
||||
menu
|
||||
.add(0, 0, 0, R.string.recovery)
|
||||
.setIcon(android.R.drawable.ic_menu_revert)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT)
|
||||
menu
|
||||
.add(0, 1, 1, R.string.about)
|
||||
.setIcon(android.R.drawable.ic_menu_info_details)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT)
|
||||
if (isRoot || Build.VERSION.SDK_INT < 17) {
|
||||
menu
|
||||
.add(0, 2, 2, R.string.flush_dnscache)
|
||||
.setIcon(android.R.drawable.ic_menu_revert)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT)
|
||||
}
|
||||
true
|
||||
}*/
|
||||
def getProfileList: List[Item] = {
|
||||
List[Item]()
|
||||
}
|
||||
|
||||
def getMenuList: List[Any] = {
|
||||
|
||||
val buf = new ListBuffer[Any]()
|
||||
|
||||
buf += new Category("Profiles")
|
||||
|
||||
buf ++= getProfileList
|
||||
|
||||
buf += new Category("Settings")
|
||||
|
||||
buf += new Item(-1, getString(R.string.recovery), android.R.drawable.ic_menu_revert,
|
||||
_ => {
|
||||
EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "reset", getVersionName, 0L)
|
||||
recovery()
|
||||
})
|
||||
|
||||
buf += new Item(-2, getString(R.string.flush_dnscache), android.R.drawable.ic_menu_delete,
|
||||
_ => {
|
||||
EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "flush_dnscache", getVersionName, 0L)
|
||||
flushDnsCache()
|
||||
})
|
||||
|
||||
buf += new Item(-3, getString(R.string.about), android.R.drawable.ic_menu_info_details,
|
||||
_ => {
|
||||
EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "about", getVersionName, 0L)
|
||||
showAbout()
|
||||
})
|
||||
|
||||
buf.toList
|
||||
|
||||
}
|
||||
|
||||
override def onKeyDown(keyCode: Int, event: KeyEvent): Boolean = {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount == 0) {
|
||||
@@ -481,18 +502,6 @@ class Shadowsocks
|
||||
drawer.toggleMenu()
|
||||
return true
|
||||
}
|
||||
case 0 => {
|
||||
EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "reset", getVersionName, 0L)
|
||||
recovery()
|
||||
}
|
||||
case 1 => {
|
||||
EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "about", getVersionName, 0L)
|
||||
showAbout()
|
||||
}
|
||||
case 2 => {
|
||||
EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "flush_dnscache", getVersionName, 0L)
|
||||
flushDnsCache()
|
||||
}
|
||||
}
|
||||
super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.github.shadowsocks.database
|
||||
|
||||
import android.content.{DialogInterface, Context}
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.BaseAdapter
|
||||
import android.widget.TextView
|
||||
import com.github.shadowsocks.R
|
||||
import android.view.View.OnClickListener
|
||||
|
||||
case class Item(id: Int, title: String, iconRes: Int, action: Int => Unit)
|
||||
|
||||
case class Category (title: String)
|
||||
|
||||
object MenuAdapter {
|
||||
|
||||
trait MenuListener {
|
||||
def onActiveViewChanged(v: View)
|
||||
}
|
||||
|
||||
val UNDEFINED = -1
|
||||
val CATEGORY = 0
|
||||
val ITEM = 1
|
||||
|
||||
}
|
||||
|
||||
class MenuAdapter (context: Context, var items: List[Any]) extends BaseAdapter {
|
||||
|
||||
def setListener(listener: MenuAdapter.MenuListener) {
|
||||
mListener = listener
|
||||
}
|
||||
|
||||
def setActivePosition(activePosition: Int) {
|
||||
mActivePosition = activePosition
|
||||
}
|
||||
|
||||
@Override def getCount: Int = {
|
||||
items.size
|
||||
}
|
||||
|
||||
@Override def getItem(position: Int): Object = {
|
||||
items(position).asInstanceOf[Object]
|
||||
}
|
||||
|
||||
@Override def getItemId(position: Int): Long = {
|
||||
position
|
||||
}
|
||||
|
||||
@Override override def getItemViewType(position: Int): Int = {
|
||||
getItem(position) match {
|
||||
case Category => MenuAdapter.CATEGORY
|
||||
case Item => MenuAdapter.ITEM
|
||||
case _ => MenuAdapter.UNDEFINED
|
||||
}
|
||||
}
|
||||
|
||||
@Override override def getViewTypeCount: Int = {
|
||||
3
|
||||
}
|
||||
|
||||
@Override override def isEnabled(position: Int): Boolean = {
|
||||
getItemViewType(position) != MenuAdapter.UNDEFINED
|
||||
}
|
||||
|
||||
@Override override def areAllItemsEnabled: Boolean = {
|
||||
false
|
||||
}
|
||||
|
||||
@Override def getView(position: Int, convertView: View, parent: ViewGroup): View = {
|
||||
var v: View = convertView
|
||||
val item = getItem(position)
|
||||
item match {
|
||||
case value: Category =>
|
||||
if (v == null) {
|
||||
v = LayoutInflater.from(context).inflate(R.layout.menu_row_category, parent, false)
|
||||
}
|
||||
v.asInstanceOf[TextView].setText(value.title)
|
||||
case value: Item =>
|
||||
if (v == null) {
|
||||
v = LayoutInflater.from(context).inflate(R.layout.menu_row_item, parent, false)
|
||||
}
|
||||
val tv: TextView = v.asInstanceOf[TextView]
|
||||
tv.setText(value.title)
|
||||
tv.setCompoundDrawablesWithIntrinsicBounds(value.iconRes, 0, 0, 0)
|
||||
tv.setOnClickListener(new OnClickListener {
|
||||
def onClick(view: View) {
|
||||
val item = view.getTag(R.id.mdItem).asInstanceOf[Item]
|
||||
item.action(item.id)
|
||||
}
|
||||
})
|
||||
|
||||
v.setTag(R.id.mdItem, value)
|
||||
case _ =>
|
||||
}
|
||||
v.setTag(R.id.mdActiveViewPosition, position)
|
||||
|
||||
if (position == mActivePosition) {
|
||||
if (mListener != null) mListener.onActiveViewChanged(v)
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
def updateList(list: List[Any]) {
|
||||
items = list
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private var mListener: MenuAdapter.MenuListener = null
|
||||
private var mActivePosition: Int = 0
|
||||
}
|
||||
|
||||
|
||||