- 浏览: 585244 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (182)
- android/ophone开发完全讲义 (4)
- android常用代码 (6)
- android工具 (9)
- android基础 (40)
- android进阶 (75)
- android经验记录 (3)
- android框架 (2)
- android面经 (5)
- android网络 (5)
- android资讯 (0)
- android资源 (17)
- 生活印象 (3)
- androidNDK (4)
- android开源 (1)
- android性能优化 (1)
- android设计 (2)
- android博客论坛收集 (1)
- android手机用户体验 (1)
- android动画 (1)
- android外文资料 (1)
- 汉字排序 (1)
最新评论
-
小猫咪201:
困惑了很久,终于找到答案了
一个常见的android内存泄露 问题 -
王雪龙:
pixels = dps * (density / 160). ...
关于Android的nodpi,xhdpi,hdpi,mdpi,ldpi -
Turr:
楼主给力,解决了我遇到的问题
解决ActivityGroup的sub Activity中spinner的WindowManager$BadTokenException的问题 -
boyuan2000cn:
你好,我转载了您的此篇博客,如果有版权问题,请告诉我,谢谢!转 ...
关于Android的nodpi,xhdpi,hdpi,mdpi,ldpi -
twlkyao:
请教您个问题,如何将drawable对象转换为id类型?
Android中Bitmap, Drawable, Byte,ID之间的转化
大家对抽屉控件的第一反应就是系统提供的 如下: 其实 该控件的原理说白了 很简单 即: * ViewGroup 如:LinearLayout 用于放置各种View * Button 用于 展开/收起 ViewGroup 所以该控件的大致布局应如下: 为了降低开发难度 我打算 定义 Panel extends LinearLayout [代码 步骤] 1. 定义一些XML用到的属性 2. 一个标准的XML为: 3. 解析该XML 并设置之 4. 设定Button 背景图 5. 取出其中的 ViewGroup & Button 6. 得到ViewGroup 宽度/高度 以决定动画演变范围 注意其位置 并非放在开始地方 因为那时候返回值都是0
7. 定义Button 响应事情 执行 开合ViewGroup 8. 定义开合的回调函数 具体效果 见:setOnClickListener(OnClickListener listener) 10. 开 即: 打开ViewGroup 11. 定义开的Animation 12. 合 即:关闭ViewGroup 13. 定义合的Animation 14. 定义二者Animation 的回调函数 即:结束后 更改Button背景图 通知OnPanelListener 15. emulator 运行截图: * 先贴其布局 * 运行截图: - 开 - 合 完工!<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Panel">
//动画演变时长
<attr name="animationDuration" format="integer" />
//摆放位置 只能取下面的4个值
<attr name="position">
<enum name="top" value="0" />
<enum name="bottom" value="1" />
<enum name="left" value="2" />
<enum name="right" value="3" />
</attr>
//开合是否有动画效果
<attr name="animationEnable" format="boolean" />
</declare-styleable>
</resources>
<org.panel.Panel
android:id="@+id/leftPanel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
panel:position="left"
panel:animationDuration="10"
panel:animationEnable="true"
android:layout_gravity="left"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<CheckBox
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Top Panel!"
android:textSize="16dip"
android:textColor="#eee"
android:textStyle="bold"
/>
<EditText
android:layout_width="200dip"
android:layout_height="wrap_content"
/>
<Button
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="OK!"
/>
</LinearLayout>
</org.panel.Panel>
public Panel(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Panel);
mDuration = a.getInteger(R.styleable.Panel_animationDuration, 750);
mPosition = a.getInteger(R.styleable.Panel_position, BOTTOM);
isAnimation = a.getBoolean(R.styleable.Panel_animationEnable, true);
a.recycle();
//根据mPosition 决定LinearLayout的android:orientation属性
mOrientation = (mPosition == TOP || mPosition == BOTTOM)? VERTICAL : HORIZONTAL;
setOrientation(mOrientation);
//初始化mHandle 背景图
initialHandlerBg();
}
//设置mHandle所用背景图
private void initialHandlerBg(){
if(mPosition == TOP){
mOpenedHandle = getResources().getDrawable(R.drawable.top_switcher_expanded_background);
mClosedHandle = getResources().getDrawable(R.drawable.top_switcher_collapsed_background);
}
else if(mPosition == BOTTOM) {
mOpenedHandle = getResources().getDrawable(R.drawable.bottom_switcher_expanded_background);
mClosedHandle = getResources().getDrawable(R.drawable.bottom_switcher_collapsed_background);
}
else if(mPosition == LEFT) {
mOpenedHandle = getResources().getDrawable(R.drawable.left_switcher_expanded_background);
mClosedHandle = getResources().getDrawable(R.drawable.left_switcher_collapsed_background);
}
else if(mPosition == RIGHT) {
mOpenedHandle = getResources().getDrawable(R.drawable.right_switcher_expanded_background);
mClosedHandle = getResources().getDrawable(R.drawable.right_switcher_collapsed_background);
}
}
//回调函数 界面初始化快结束时调用 用于得到 mHandle/mContent
protected void onFinishInflate() {
super.onFinishInflate();
//得到mHandle实例
mHandle = this.getChildAt(0);
if (mHandle == null) {
throw new RuntimeException("Your Panel must have a View - mHandle");
}
mHandle.setOnClickListener(clickListener);
//得到mContent实例
mContent = this.getChildAt(1);
if (mContent == null) {
throw new RuntimeException("Your Panel must have a View - mContent");
}
//先移除mHandle/mContent 然后根据position决定二者的添加次序
removeView(mHandle);
removeView(mContent);
if (mPosition == TOP || mPosition == LEFT) {
addView(mContent);
addView(mHandle);
} else {
addView(mHandle);
addView(mContent);
}
if (mClosedHandle != null) {
mHandle.setBackgroundDrawable(mClosedHandle);
}
//隐藏 mContent
mContent.setVisibility(GONE);
}
@Override //回调函数 此时其内所有子View 宽度/高度 都已确定
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mContentWidth = mContent.getWidth();
mContentHeight = mContent.getHeight();
paddingTop = this.getPaddingTop();
paddingLeft = this.getPaddingLeft();
}
// 定义mHandle监听器 用于开合mContent
OnClickListener clickListener = new OnClickListener(){
public void onClick(View v) {
// TODO Auto-generated method stub
if(!isContentExpand){
open();
}
else {
close();
}
//置反 即:开-合-开-合-开-...
isContentExpand = !isContentExpand;
}
};
//回调函数 用于监听 Panel 的开合 效果见:setOnClickLstener(OnClickListener listener)
public static interface OnPanelListener {
//- open
public void onPanelOpened(Panel panel);
//- close
public void onPanelClosed(Panel panel);
}
public void open(){
if(isAnimation){
doAnimationOpen();
}
else {
doOpen();
}
}
public void doOpen(){
mContent.setVisibility(VISIBLE);
}
public void doAnimationOpen(){
mContent.setVisibility(VISIBLE);
post(aOpen);
}
//- open
Runnable aOpen = new Runnable() {
public void run() {
TranslateAnimation animation;
int fromXDelta = 0, toXDelta = 0, fromYDelta = 0, toYDelta = 0;
int calculatedDuration = 0;
if(mPosition == TOP){
fromYDelta = -1 * mContentHeight;
toXDelta = 0;
calculatedDuration = mDuration * Math.abs(toYDelta - fromYDelta) / mContentHeight;
}
else if(mPosition == BOTTOM){
fromYDelta = paddingTop;
toYDelta = fromYDelta + 1 * mContentHeight;
calculatedDuration = mDuration * Math.abs(toYDelta - fromYDelta) / mContentHeight;
}
else if(mPosition == LEFT){
fromXDelta = -1 * mContentWidth;
toXDelta = 0;
calculatedDuration = mDuration * Math.abs(toXDelta - fromXDelta) / mContentWidth;
}
else if(mPosition == RIGHT){
fromXDelta = paddingLeft;
toXDelta = fromYDelta + 1 * mContentHeight;
calculatedDuration = mDuration * Math.abs(toYDelta - fromYDelta) / mContentHeight;
}
animation = new TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);
animation.setDuration(calculatedDuration);
animation.setAnimationListener(aOListener);
startAnimation(animation);
}
};
public void close(){
if(isAnimation){
doAnimationClose();
}
else {
doClose();
}
}
public void doClose(){
mContent.setVisibility(GONE);
}
public void doAnimationClose(){
post(aClose);
}
//- close
Runnable aClose = new Runnable() {
public void run() {
TranslateAnimation animation;
int fromXDelta = 0, toXDelta = 0, fromYDelta = 0, toYDelta = 0;
int calculatedDuration = 0;
if(mPosition == TOP){
toYDelta = -1 * mContentHeight;
calculatedDuration = mDuration * Math.abs(toYDelta - fromYDelta) / mContentHeight;
}
else if(mPosition == BOTTOM){
fromYDelta = 1 * mContentHeight;
toYDelta = paddingTop;
calculatedDuration = mDuration * Math.abs(toYDelta - fromYDelta) / mContentHeight;
}
else if(mPosition == LEFT){
toXDelta = -1 * mContentWidth;
calculatedDuration = mDuration * Math.abs(toXDelta - fromXDelta) / mContentWidth;
}
else if(mPosition == RIGHT){
}
animation = new TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);
animation.setDuration(calculatedDuration);
animation.setAnimationListener(aCListener);
startAnimation(animation);
}
};
//善后工作 比如:改变mHandle背景图 通知开合监听器
private void postProcess() {
// to update mHandle 's background
if (!isContentExpand ) {
mHandle.setBackgroundDrawable(mClosedHandle);
}
else {
mHandle.setBackgroundDrawable(mOpenedHandle);
}
// invoke listener if any
if (panelListener != null) {
if (isContentExpand) {
panelListener.onPanelOpened(Panel.this);
}
else {
panelListener.onPanelClosed(Panel.this);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:panel="http://schemas.android.com/apk/res/org.panel"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<org.panel.Panel
android:id="@+id/leftPanel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
panel:position="left"
panel:animationDuration="10"
panel:animationEnable="true"
android:layout_gravity="left"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<CheckBox
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Top Panel!"
android:textSize="16dip"
android:textColor="#eee"
android:textStyle="bold"
/>
<EditText
android:layout_width="200dip"
android:layout_height="wrap_content"
/>
<Button
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="OK!"
/>
</LinearLayout>
</org.panel.Panel>
<org.panel.Panel
android:id="@+id/rightPanel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
panel:position="right"
panel:animationDuration="10"
panel:animationEnable="true"
android:layout_gravity="right"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/beijing4_b"
/>
</LinearLayout>
</org.panel.Panel>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="16dip"
android:textColor="#ddd"
android:text="other area!!!!!!!!"
/>
<Button
android:id="@+id/button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="Yes!"
/>
</LinearLayout>
</LinearLayout>
发表评论
-
Android 检查当前是否已经连接上 Internet
2012-02-27 09:28 1java代码: 1 ConnectivityManager ... -
对ContentProvider中getType(Uri uri)和android.intent.category.DEFAULT的理解
2012-02-27 09:21 1630学习了ContentProvider,想做个通讯录,结果 ... -
Android ContentProvider的介绍(很详细)
2012-02-21 17:46 139652一、ContentProvider的概念 Content ... -
一个常见的android内存泄露 问题
2012-02-20 16:11 4938最近在公司看一个算比较大的android项目的源码, ... -
一个常见的android内存泄露 问题
2012-02-20 16:10 0最近在公司看一个算比较大的android项目的源码,发 ... -
Android网络电台的一种实现方案
2012-02-20 15:12 3674随着电子产品的飞速 ... -
NotificationManager和Notification的使用总结
2012-02-16 15:55 1137这几天一直在修改twigee的源代码,其中一个要加入的 ... -
android 如何判断程序是否在前台运行
2012-02-16 15:31 5451private boolean isTopActivit ... -
Android Intent和PendingIntent的区别详细分析
2012-02-16 14:08 1560刚才一个例子中用到了PendingIntent,与之前学过的I ... -
编码问题(UTF-8、gb2312、unicode)
2012-02-14 09:38 1949相信大家很多人跟我一样,对于编码一直感觉云山雾罩,说知道吧?就 ... -
关于androidSDK登录时出现oauth2.0空白页的BUG
2012-02-09 16:21 1421在RenrenListenerFactory中,line 12 ... -
java中yield(),sleep()以及wait()的区别
2012-01-31 18:41 956往往混淆了这三个函数的使用。 从操作系统的角度讲, ... -
Toast大全(五种情形)建立属于你自己的Toast
2012-01-29 17:23 1588Toast用于向用户显示一些帮助/提示。下面我做了5中效果 ... -
Android主流屏幕分辨率介绍
2012-01-18 14:45 1419对于Android游戏开发我们不得不像iPhone那样思 ... -
关于混淆外包jar包出错的解决方法
2012-01-18 11:30 1796-optimizationpasses 5-do ... -
新浪微博SDK
2011-12-28 16:38 1191DEMO程序:http://code.google.co ... -
Android中自定义Dialog外形,去除黑底和白色边框
2011-12-08 16:29 7468在做Android开发中经常会使用到自定义样式的Dialo ... -
汉字排序
2011-12-07 09:44 1092Comparator comparator = Coll ... -
Android TextView中文字通过SpannableString来设置超链接、颜色、字体等属性
2011-11-29 19:29 13633在Android中,TextView是我们最常用的用来显示文本 ... -
屏幕分辨率适配
2011-10-19 18:55 3135屏幕分辨率:1024x600 d ...
相关推荐
在Android应用开发中,滑动抽屉Panel是一种常见的设计模式,它允许用户通过从屏幕边缘向内滑动来显示或隐藏附加内容。本资源“自定义Android滑动抽屉Panel.zip”提供了一个自定义实现这一功能的示例,包含源码和相关...
在C#中,我们可以利用控件(如Panel或Form)的移动和大小调整功能来实现抽屉效果。以下是一些关键步骤: 1. 创建主窗体:首先,创建一个主窗体作为QQ界面的基础,设置其大小和布局。你可以使用Visual Studio的窗体...
在Android应用开发中,抽屉组件(Drawer Layout)是一种常见的...ExPanel(1)作为一个示例,为我们提供了一种可能的实现方式,通过研究其源码,我们可以学习到更多的技巧和最佳实践,进一步提升我们的Android开发能力。
例如,`Switcher.class`可能表示一个自定义的切换视图类,`Panel.class`可能是实现抽屉效果的类,而`TestInterpolators$2.class`可能是一个测试不同动画插值器效果的辅助类。 综上所述,这个压缩包是一个全面的...
"core-drawer-panel"是基于Polymer 0.5框架的一个...对于想要学习或重温这个组件的开发者,可以从名为"core-drawer-panel-master"的压缩包文件中获取源代码,研究其工作原理,但应意识到这只是一个历史性的参考资料。
在这里,开发者可能定义了一个隐藏的Panel或者UserControl作为菜单容器,然后在用户触发特定事件(如点击按钮)时,通过调整其位置和宽度来模拟抽屉滑出的效果。这通常涉及到对控件的Size、Location属性的动态修改,...
例如,一个常见的自定义Panel是底部导航抽屉,用户可以从中选择不同的功能模块。 2. 空键(Empty View): 空键是当数据为空时展示的一种特殊视图,它向用户传达了当前无数据可用的信息。在设计用户界面时,为了...
项目中可能包含的Widgets有:滑动面板(SlidingPanel)、折叠面板(CollapsiblePanel)、抽屉面板(DrawerPanel)等。这些Widgets通常具有自定义布局、动画效果和触摸交互特性,使得开发者可以轻松地定制符合应用...
侧窗是jQuery Mobile中的一种布局元素,常用于实现类似抽屉的效果,可以隐藏或显示附加信息。创建侧窗需要通过HTML5的`<div>`标签,并设置相应的类名,如`<div data-role="panel" id="myPanel">`。通过JavaScript...
在Qt5框架中,`QSidePanel`是一个自定义控件,它被设计用来作为界面中的侧边栏或抽屉式面板。这个组件通常用于显示附加信息、菜单选项或者工具栏,可以方便地进行展开和收起,为用户提供更加灵活的交互体验。`...
3. **侧滑面板(Swipeable Panel)**:侧滑面板通常用于实现类似抽屉式的效果,比如谷歌地图中的侧滑导航栏。可以使用CoordinatorLayout结合Behavior来实现,也可以使用DrawerLayout。主要关注滑动手势的识别和面板...
1. **Android Sliding Up Panel**:这是一个可滑动的顶部和底部面板库,可以用于创建类似Google Play音乐应用的侧滑效果。 2. **Android DrawerLayout**:这是Android SDK中内置的一个组件,用于创建抽屉式导航菜单...
这个项目主要是为 iOS 应用程序提供一种灵活的、可自定义的面板(Panel)展示方式。在 iOS 开发中,面板通常用于创建滑出式菜单、模态视图或者浮动操作按钮等交互元素,为用户界面增加丰富的动态效果。 【描述】...
向右滑动,则会隐藏,通常用于实现类似抽屉式的导航菜单。 要实现部分可见和淡入淡出效果,开发者需要对SlidingPaneLayout的一些关键属性进行调整。例如,可以设置`overhangSize`属性,使得滑动视图在完全滑出前...
这部分内容讨论了不同的导航模式,如抽屉式导航栏、底部导航栏等,并给出了具体的实现建议。 #### 二十、ActionBar - 动作栏 动作栏是Android应用中非常重要的组成部分。这部分内容介绍了如何设计和实现动作栏,使...