①项目架构
其实这个布局我一开始没想过做侧滑菜单,最后其实用我自己的框架 已经把基本页面做完了,但是,最后上拉加载更多卡住了,最后李老师帮我把架构重构了一下,最后得以完成感谢李老师
主布局相信大家都看得出来 pullrefesh 加下滑菜单 我再想我该怎么写这一篇文章呢,因为这涉及到自定义的类,抽取到了一个类了,我觉得还是一个一个知识点讲吧
② 侧滑菜单Slidingmenu
一 什么是SlidingMenu
SlidingMenu是一种比较新的设置界面或配置界面的效果,在主界面左滑或者右滑出现设置界面效果,能方便的进行各种操作。很多优秀的应用都采用了这种界面方案,像facebook、人人网、everynote、Google+等等
二 配置SlidingMenu
下载地址
侧滑菜单 :SlidingMenu:https://github.com/jfeinstein10/SlidingMenu
依赖包 : ActionBarSherlock:https://github.com/JakeWharton/ActionBarSherlock
解决错误
1.重新配置Library链接
2.删除SlidingMenu类库中自带的support-v4.jar
3.配置SlidingMenu引用ActionBarSherlock类库
4.修改SlidingMenu类库下SlidingFragmentActivity继承SherlockFragmentActivity
常用属性
设置左滑菜单 menu.setMode(SlidingMenu.LEFT);
设置滑动的模式 menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
设置阴影 menu.setShadowDrawable(R.drawable.shadow);
设置阴影的宽度 menu.setShadowWidthRes(R.dimen.shadow_width);
划出时主页面显示的剩余宽度 menu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
菜单的宽度 menu.setBehindWidth(400);
滑动时的渐变程度 menu.setFadeDegree(0.35f);
附加在Activity上 menu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
设置menu的布局文件
menu.setMenu(R.layout.menu_layout);
动态断定主动封闭或开启 menu.toggle();
显示
menu.showMenu();
显示内容
menu.showContent();
监听器 打开 menu.setOnOpenListener(onOpenListener); 关闭menu.OnClosedListener(OnClosedListener);
设置左右菜单
设置右侧阴影 sm.setSecondaryShadowDrawable(R.drawable.shadowright);
设置右侧菜单布局 sm.setSecondaryMenu(R.layout.menu_frame2);
看不下去了吧 还是直接看图片吧
三应用SlidingMenu
1.Activity实现SlidingMenu
// 实例化一个SlidingMenu
slidingMenu = new SlidingMenu(this);
// 设置为左侧滑动模式
slidingMenu.setMode(SlidingMenu.LEFT);
// 设置全屏触发滑动
slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
// 设置阴影效果
slidingMenu.setShadowDrawable(R.drawable.shadow);
// 设置阴影宽度
slidingMenu.setShadowWidth(3);
// 设置滑出时主页面显示的剩余宽度
slidingMenu.setBehindOffset(10);
// 设置滑出的宽度
slidingMenu.setBehindWidth(350);
// 设置淡入淡出效果
slidingMenu.setFadeDegree(0.35f);
// 设置依附于Activity
slidingMenu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
// 设置左侧滑出菜单的布局
slidingMenu.setMenu(R.layout.slidingmenu_test);
2.SlidingMenu里的点击事务
因为SlidingMenu已经被包含在了Activity中了,所以直接findViewById(id),拿到view之后就可以进行响应的处理
其实从Slidingmenu 源码中可以看出来,他一般是和ActionBarSherlock ,Fragment 所以主布局就是 就是一个标题+Fragment SO--------
我用了一个Framelayout+自定义title
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.qf.teach.project.zhihudaily.custom.CustomTitle
android:id="@+id/custom_title"
android:layout_width="match_parent"
android:layout_height="60dp" />
<FrameLayout
android:id="@+id/fl_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
四 自定义title
不知道大家还记不记得自定义,首先你要继承一个一样东西,然后重写 带两个参数的构造方法 将布局填充进去,然后定义一个你需要的方法,这里既然我们需要一个设置title文字的方法
package com.qf.teach.project.zhihudaily.custom;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.qf.teach.project.zhihudaily.R;
/**
* 自定义标题
* @author Lusifer
*
* 2014年12月1日下午2:32:33
*/
public class CustomTitle extends FrameLayout {
private TextView txTitle;
public CustomTitle(Context context, AttributeSet attrs) {
super(context, attrs);
// 绑定布局
LayoutInflater.from(context).inflate(R.layout.custom_title, this);
initView();
}
private void initView() {
txTitle = (TextView) findViewById(R.id.tx_title);
}
public void setTitle(String title) {
txTitle.setText(title);
}
}
回到java代码
③ 初始化界面
既然要用到Fragment 所以我们activity 就继承了 FragmentActivity 用Fragment去取代其中的Framelayout
一初始化组件
/**
* 初始化界面(Fragment)
*/
private void initView() {
cTitle = (CustomTitle) findViewById(R.id.custom_title);
cTitle.setTitle("首页");
cTitle.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// slidingmenu动态断定主动封闭或开启
menu.toggle();
}
});
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fl_content, MainFragment.newInstance());
fragmentTransaction.commit();
}
二初始化Slidingmenu
相信经过上面讲解Slidingmenu 大家应该都知道怎么应用Slidingmenu 了,先看Slidingmenu的界面吧,其实也是要加载数据的
其中也就是一个listview需要获取列表的数据
/**
* 初始化SlidingMenu
*/
private void initSlidingMenu() {
mQueue = Volley.newRequestQueue(getApplicationContext());
// 菜单
menu = new SlidingMenu(this);
menu.setMode(SlidingMenu.LEFT);
menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
menu.setShadowWidth(10);
menu.setShadowDrawable(R.drawable.shadow);
menu.setBehindOffset(100);
menu.setFadeDegree(0.35f);
menu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
menu.setMenu(R.layout.sliding_left);
// 主题
adapter = new MyBaseAdapter();
//listview加载数据
lvTheme = (ListView) findViewById(R.id.lv_theme);
lvTheme.setOnItemClickListener(this);
lvTheme.setAdapter(adapter);
mQueue.add(new JsonObjectRequest(Method.GET, API.getThemesUrl(), null, this, null));
}
上面菜单那一段代码 相信大家都懂,下面那个主题,也就是Slidingmenu 里面的东西 要进行联网将数据拿下来 填充到Baseadapter里面去
(1)用volly进行联网请求数据拿到json
注意到上面的这两句话,其实真正的URL已经不在java代码里了,而在jni里面,就算反编译也得不到..............
mQueue = Volley.newRequestQueue(getApplicationContext());
mQueue.add(new JsonObjectRequest(Method.GET, API.getThemesUrl(), null, this, null));
然后让我们看看json结构,最外层是一个大括号,所以vally的用jsonobject 相信大家json解析还是会的
根据 json结构先建立 实体类 里面有两个数组 SO
package com.qf.teach.project.zhihudaily.entity;
import java.util.List;
public class Theme {
private int limit;
private List<ThemeOther> others;
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public List<ThemeOther> getOthers() {
return others;
}
public void setOthers(List<ThemeOther> others) {
this.others = others;
}
}
package com.qf.teach.project.zhihudaily.entity;
public class ThemeOther {
private int color;
private String image;
private String description;
private long id;
private String name;
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/* -------------------- 网络请求 -------------------- */
@Override
public void onResponse(JSONObject response) {
theme = new Theme();
try {
theme.setLimit(response.getInt("limit"));
// 解析Others
JSONArray jsonArray = response.getJSONArray("others");
if (jsonArray != null && jsonArray.length() > 0) {
List<ThemeOther> others = new ArrayList<ThemeOther>();
// 手动增加首页
ThemeOther other = new ThemeOther();
other.setName("首页");
others.add(other);
// 解析
for (int i = 0 ; i < jsonArray.length() ; i++) {
JSONObject obj = jsonArray.getJSONObject(i);
other = new ThemeOther();
other.setColor(obj.getInt("color"));
other.setDescription(obj.getString("description"));
other.setId(obj.getLong("id"));
other.setImage(obj.getString("image"));
other.setName(obj.getString("name"));
others.add(other);
}
theme.setOthers(others);
adapter.notifyDataSetChanged();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
/* -------------------- 网络请求 -------------------- */
(2)实例化Adapter并进行填充数据
adapter 其实就写在mainactivity类中,所以可以省略了传值问题,其中也对Listview 进行了优化比如复用convertView 减少系统findByid的次数
/**
* ThemeAdapter
* @author Lusifer
*
* 2014年12月4日下午2:11:55
*/
class MyBaseAdapter extends BaseAdapter {
private ViewHolder viewHolder;
@Override
public int getCount() {
return theme == null ? 0 : theme.getOthers().size();
}
@Override
public Object getItem(int position) {
return theme.getOthers().get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.list_theme, parent, false);
viewHolder = new ViewHolder();
viewHolder.txTitle = (TextView) convertView.findViewById(R.id.tx_title);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
ThemeOther other = theme.getOthers().get(position);
viewHolder.txTitle.setText(other.getName());
return convertView;
}
class ViewHolder {
public TextView txTitle;
}
}
OK 到这里 Slidingmenu里面的数据 也就填充上去了
End