程序员人生 网站导航

项目实战①―高仿知乎日报(2)―>使用pullrefesh+Slidingmenu+自定义组件写主布局

栏目:综合技术时间:2014-12-18 08:56:59


①项目架构

其实这个布局我1开始没想过做侧滑菜单,最后其实用我自己的框架 已把基本页面做完了,但是,最后上拉加载更多卡住了,最后李老师帮我把架构重构了1下,最后得以完成感谢李老师

主布局相信大家都看得出来 pullrefesh 加下滑菜单 我再想我该怎样写这1篇文章呢,由于这触及到自定义的类,抽取到了1个类了,我觉得还是1个1个知识点讲吧


② 侧滑菜单Slidingmenu


1 甚么是SlidingMenu

SlidingMenu是1种比较新的设置界面或配置界面的效果,在主界面左滑或右滑出现设置界面效果,能方便的进行各种操作。很多优秀的利用都采取了这类界面方案,像facebook、人人网、everynote、Google+等等

2 配置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);  

看不下去了吧 还是直接看图片吧





3利用SlidingMenu

1.Activity实现SlidingMenu

// 实例化1个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 源码中可以看出来,他1般是和ActionBarSherlock ,Fragment  所以主布局就是 就是1个标题+Fragment  SO--------
我用了1个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>

4 自定义title

不知道大家还记不记得自定义,首先你要继承1个1样东西,然后重写 带两个参数的构造方法 将布局填充进去,然后定义1个你需要的方法,这里既然我们需要1个设置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

1初始化组件


/** * 初始化界面(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(); }

2初始化Slidingmenu 

相信经过上面讲授Slidingmenu 大家应当都知道怎样利用Slidingmenu 了,先看Slidingmenu的界面吧,其实也是要加载数据的 




其中也就是1个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)); }


上面菜单那1段代码 相信大家都懂,下面那个主题,也就是Slidingmenu 里面的东西 要进行联网将数据拿下来 填充到Baseadapter里面去
(1)用volly进行联网要求数据拿到json

  注意到上面的这两句话,其实真实的URL已不在java代码里了,而在jni里面,就算反编译也得不到..............

mQueue = Volley.newRequestQueue(getApplicationContext());
mQueue.add(new JsonObjectRequest(Method.GET, API.getThemesUrl(), null, this, null));

然后让我们看看json结构,最外层是1个大括号,所以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

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐