Android组件——使用DrawerLayout仿网易新闻v4.4侧滑菜单

转载请注明出处:http://blog.csdn.net/allen315410/article/details/42914501

概述

今天这篇博客将记录一些关于DrawerLayout的基本用法,我想关于DrawerLayout的用法也许有不少不够了解,这也是比较正常的事情,因为DrawerLayout作为Android组件是Google后来在android中添加的,在android.support.v4包下。那么,DrawerLayout是一个怎么的组件呢?我们知道,当我们使用Android上各类App的时候,是不是注意过App主页上通常有一个“侧滑菜单”?关于侧滑菜单的实现,我在前面博客里有一些介绍,想多些了解的朋友请移步:

Android自定义控件——侧滑菜单

Android自定义控件——开源组件SlidingMenu的项目集成

这里用“网易新闻”客户端v4.4的截图来说明一下,这个DrawerLayout抽屉式布局是什么样子的。

   

好,大家已经看到了,网易新闻客户端效果很明显,当我们手指在屏幕左侧向右滑动时候,就会有一个抽屉式的菜单从左边弹出,并且是“悬浮”在主界面之上的,合理的利用了设备上有限的空间,同样手指在屏幕右侧向左滑动也会出现一个向左弹出的抽屉式菜单,用户体验效果还是不错的,在DrawerLayout出现之前,我们需要做侧滑菜单时,不得不自己实现一个或者使用Github上的开源的项目SlidingMenu,也许是Google也看到了SlidingMenu的强大之处,于是在Android的后期版本中添加了DrawerLayout来实现SlidingMenu同样功能的组件,而且为了兼容早期版本,将其添加在android,support.v4包下。

关于DrawerLayout的Training:http://developer.android.com/training/implementing-navigation/nav-drawer.html

关于DrawerLayout的API:http://developer.android.com/reference/android/support/v4/widget/DrawerLayout.html

另外,我已经翻译过了Google的Training课程,地址是:http://blog.csdn.net/allen315410/article/details/42875231

效果预览

创建抽屉布局

下面这个抽屉布局引用的是android.support.v4.DrawerLayout,类似于LineaLayout、RelativeLayout等布局一样定义,在DrawerLayout内部再定义3个布局,分别是管理主界面的FrameLayout,此布局用来展示界面切换的Fragment,下面是ListView,用来展示菜单列表,最后是一个RelativeLayout,用来展示右边的布局,布局代码如下:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="200dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#111"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp" />

    <RelativeLayout
        android:id="@+id/right_drawer"
        android:layout_width="220dp"
        android:layout_height="match_parent"
        android:layout_gravity="end"
        android:background="#111"
        android:gravity="center_horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="这是右边栏"
            android:textColor="@android:color/white"
            android:textSize="24sp" />
    </RelativeLayout>

</android.support.v4.widget.DrawerLayout>

这个布局文件示范了一些重要的布局特征.

  • 主要内容的视图(FrameLayout)必须是DrawLayout的第一个子元素, 因为导航抽屉是在主要内容视图的上面.
  • 主要内容视图设置为匹配父视图的宽度和高度, 因为它代表了整个界面导航抽屉是隐藏的.
  • 抽屉视图(ListView)必须指定其水平重力与android:layout_gravity属性。支持从右到左(RTL)语言,指定值与 "start" 代替 "left"(所以抽屉里出现在布局的右侧当布局是RTL时).这里将ListView设置为左边栏菜单,所以android:layout_gravity属性设置为“start”,将RelativeLayout设置为右边栏,设置android:layout_gravity属性为“end”.
  • 抽屉视图指定其宽度用dp单位和高度匹配父视图。抽屉里的宽度不能超过320 dp, 所以用户总是可以看到主要内容视图的一部分。

初始化抽屉列表

正如上述所讲,因为DrawerLayout里包含一个ListView作为左边栏侧滑菜单,所以我们需要首先初始化这个抽屉列表,并且为这个列表适配上数据,数据适配器使用的是最简单的ArrayAdapter,模拟数据被简单的定义在res/values/strings.xml里,如下:

 <string-array name="menu_array">
        <item>Menu 1</item>
        <item>Menu 2</item>
        <item>Menu 3</item>
        <item>Menu 4</item>
 </string-array>

在Java代码中,首先创建一个MainActivity继承了android.support.v4.app.FragmentActivity,因为后续中需要进行Fragment之间的切换。

protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
        ......
	// 初始化菜单列表
	mMenuTitles = getResources().getStringArray(R.array.menu_array);
	mMenuListView.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, mMenuTitles));
	mMenuListView.setOnItemClickListener(new DrawerItemClickListener());
        ......
}

处理导航点击事件

当用户选择了抽屉列表里面的一个Item时, 系统调用onItemClickListener上的onItemClick(), 给setOnItemClickListener()你在onItemClick()方法里面做什么,在下面的例子中, 选择每一个Item都会在主要内容的布局中插入一个不同的Fragment.并且将导航列表的内容传递给Fragment中显示出来,下面是部分代码:

/**
 * ListView上的Item点击事件
 *
 */
private class DrawerItemClickListener implements ListView.OnItemClickListener {
	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
		selectItem(position);
	}
}

/**
 * 切换主视图区域的Fragment
 *
 * @param position
 */
private void selectItem(int position) {
	// TODO Auto-generated method stub
	Fragment fragment = new ContentFragment();
	Bundle args = new Bundle();
	switch (position) {
	case 0:
		args.putString("key", mMenuTitles[position]);
		break;
	case 1:
		args.putString("key", mMenuTitles[position]);
		break;
	case 2:
		args.putString("key", mMenuTitles[position]);
		break;
	case 3:
		args.putString("key", mMenuTitles[position]);
		break;
	default:
		break;
	}
	fragment.setArguments(args); // FragmentActivity将点击的菜单列表标题传递给Fragment
	FragmentManager fragmentManager = getSupportFragmentManager();
	fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();

	// 更新选择后的item和title,然后关闭菜单
	mMenuListView.setItemChecked(position, true);
	setTitle(mMenuTitles[position]);
	mDrawerLayout.closeDrawer(mMenuListView);
}

开源material-menu的集成

细心的朋友也许会发现“网易新闻”v4.4客户端主页左上角上有个菜单“动态”的菜单按钮,显示流程是这样的,当菜单没有打开时,显示“三”这样的三条横线,当菜单打开(无论左右菜单)时,会显示“<-”这样的按钮,不停的变化,这样的效果是不是有点绚丽啊?!了解过Android5.0的朋友,应该会知道这种效果是使用了Android5.0新推出的Material Design设计语言做出来的效果,那么该怎么模仿这个效果呢?不好意思,由于偷懒,我已经在牛牛的Github中找到了这样的效果——material-menu组件,该组件模拟出了Android5.0下的Material
Design效果,注意的是该组件中使用了JackWharton的NineOldAndroids动画效果。

material-menu主页:https://github.com/balysv/material-menu

NineOldAndroids主页:https://github.com/JakeWharton/NineOldAndroids

关于material-menu的使用可以参考其主页上的Demo和说明,集成时需要下载NineOldAndroids导出jar集成到项目中。下面是我使用的部分代码:

protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
        ......
	// 设置抽屉打开时,主要内容区被自定义阴影覆盖
	mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
	// 设置ActionBar可见,并且切换菜单和内容视图
	getActionBar().setDisplayHomeAsUpEnabled(true);
	getActionBar().setHomeButtonEnabled(true);

	mMaterialMenuIcon = new MaterialMenuIcon(this, Color.WHITE, Stroke.THIN);

	mDrawerLayout.setDrawerListener(new DrawerLayout.SimpleDrawerListener() {

		@Override
		public void onDrawerSlide(View drawerView, float slideOffset) {
			showView = drawerView;
			if (drawerView == mMenuListView) {
				mMaterialMenuIcon.setTransformationOffset(MaterialMenuDrawable.AnimationState.BURGER_ARROW, isDirection_left ? 2 - slideOffset : slideOffset);
			} else if (drawerView == right_drawer) {
				mMaterialMenuIcon.setTransformationOffset(MaterialMenuDrawable.AnimationState.BURGER_ARROW, isDirection_right ? 2 - slideOffset : slideOffset);
			}
		}

		@Override
		public void onDrawerOpened(android.view.View drawerView) {
			if (drawerView == mMenuListView) {
				isDirection_left = true;
			} else if (drawerView == right_drawer) {
				isDirection_right = true;
			}
		}

		@Override
		public void onDrawerClosed(android.view.View drawerView) {
			if (drawerView == mMenuListView) {
				isDirection_left = false;
			} else if (drawerView == right_drawer) {
				isDirection_right = false;
				showView = mMenuListView;
			}
		}
	});
        ......

}

此外,还需要关联一下meterial-menu的状态,需要覆盖Activity下的onPostCreate和onSaveInstanceState方法:

/**
* 根据onPostCreate回调的状态,还原对应的icon state
*/
@Override
protected void onPostCreate(Bundle savedInstanceState) {
	super.onPostCreate(savedInstanceState);
	mMaterialMenuIcon.syncState(savedInstanceState);
}

/**
* 根据onSaveInstanceState回调的状态,保存当前icon state
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
	mMaterialMenuIcon.onSaveInstanceState(outState);
	super.onSaveInstanceState(outState);
}

添加ActionBar上的菜单按钮

为了尽量模拟出“网易新闻”v4.4客户端主页,我也在标题栏右上角添加一个小图标,为了能在点击这个小图标的时候弹出右边栏菜单,实现方式很简单,关于ActionBar上添加导航的知识可以在csdn上搜到一些解释或者上Android开发者官网查看源文档,我这里首先简单的在res/menu下main.xml中这样定义一个:

<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/action_personal"
        android:icon="@drawable/action_personal"
        android:orderInCategory="100"
        android:showAsAction="always"
        android:title="@string/action_personal"/>

</menu>

完成定义操作后,需要加载菜单布局:

/**
* 加载菜单
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
	// Inflate the menu; this adds items to the action bar if it is present.
	getMenuInflater().inflate(R.menu.main, menu);
	return true;
}

标题栏导航点击事件处理

/**
* 点击ActionBar上菜单
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
	int id = item.getItemId();
	switch (id) {
	case android.R.id.home:
		if (showView == mMenuListView) {
			if (!isDirection_left) { // 左边栏菜单关闭时,打开
				mDrawerLayout.openDrawer(mMenuListView);
			} else {// 左边栏菜单打开时,关闭
				mDrawerLayout.closeDrawer(mMenuListView);
			}
		} else if (showView == right_drawer) {
			if (!isDirection_right) {// 右边栏关闭时,打开
				mDrawerLayout.openDrawer(right_drawer);
			} else {// 右边栏打开时,关闭
				mDrawerLayout.closeDrawer(right_drawer);
			}
		}
		break;
	case R.id.action_personal:
		if (!isDirection_right) {// 右边栏关闭时,打开
			if (showView == mMenuListView) {
				mDrawerLayout.closeDrawer(mMenuListView);
			}
			mDrawerLayout.openDrawer(right_drawer);
		} else {// 右边栏打开时,关闭
			mDrawerLayout.closeDrawer(right_drawer);
		}
		break;
	default:
		break;
	}
	return super.onOptionsItemSelected(item);
}

这段的逻辑有点绕,事实上我做的是这样的,需要保证主界面上只能最多显示一个菜单布局,当左边的菜单布局展示时,此时打开右边菜单布局时,需要隐藏左边菜单布局;同样,如果右边的菜单布局已经在展示的时候,这时需要打开左边菜单布局,必须首先隐藏掉右边的菜单布局。为了判断当前即将显示或者关闭的是哪个布局,我在全局变量中定义了showView用来标记当前即将显示或者关闭的视图,如果showView==mMenuListView,说明左边菜单布局是即将被显示或隐藏的,这时进一步判断菜单是视图mMenuListView的是否已经显示的标记isDirection_left,来打开或者关闭左边视图菜单。

同样的道理,如果当前即将显示或者隐藏的是右边导航菜单的话,我们需要进一步判断右边导航是否已经显示,从而进行相关打开或隐藏的决定。

这里的逻辑似乎解释的有点乱,而且代码是分片段贴出来的,不利于理解,需要进一步理解的话,不妨继续看下面的部分,我已经贴出了所以的Java代码,注释也很详尽,可以方便理解,实在不行,还可以点击博客下方的下载链接,直接下载源码运行一下。

全部源码

public class MainActivity extends FragmentActivity {

	/** DrawerLayout */
	private DrawerLayout mDrawerLayout;
	/** 左边栏菜单 */
	private ListView mMenuListView;
	/** 右边栏 */
	private RelativeLayout right_drawer;
	/** 菜单列表 */
	private String[] mMenuTitles;
	/** Material Design风格 */
	private MaterialMenuIcon mMaterialMenuIcon;
	/** 菜单打开/关闭状态 */
	private boolean isDirection_left = false;
	/** 右边栏打开/关闭状态 */
	private boolean isDirection_right = false;
	private View showView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
		mMenuListView = (ListView) findViewById(R.id.left_drawer);
		right_drawer = (RelativeLayout) findViewById(R.id.right_drawer);
		this.showView = mMenuListView;

		// 初始化菜单列表
		mMenuTitles = getResources().getStringArray(R.array.menu_array);
		mMenuListView.setAdapter(new ArrayAdapter<String>(this,
				R.layout.drawer_list_item, mMenuTitles));
		mMenuListView.setOnItemClickListener(new DrawerItemClickListener());

		// 设置抽屉打开时,主要内容区被自定义阴影覆盖
		mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
				GravityCompat.START);
		// 设置ActionBar可见,并且切换菜单和内容视图
		getActionBar().setDisplayHomeAsUpEnabled(true);
		getActionBar().setHomeButtonEnabled(true);

		mMaterialMenuIcon = new MaterialMenuIcon(this, Color.WHITE, Stroke.THIN);
		mDrawerLayout.setDrawerListener(new DrawerLayoutStateListener());

		if (savedInstanceState == null) {
			selectItem(0);
		}

	}

	/**
	 * ListView上的Item点击事件
	 *
	 */
	private class DrawerItemClickListener implements
			ListView.OnItemClickListener {
		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position,
				long id) {
			selectItem(position);
		}
	}

	/**
	 * DrawerLayout状态变化监听
	 */
	private class DrawerLayoutStateListener extends
			DrawerLayout.SimpleDrawerListener {
		/**
		 * 当导航菜单滑动的时候被执行
		 */
		@Override
		public void onDrawerSlide(View drawerView, float slideOffset) {
			showView = drawerView;
			if (drawerView == mMenuListView) {// 根据isDirection_left决定执行动画
				mMaterialMenuIcon.setTransformationOffset(
						MaterialMenuDrawable.AnimationState.BURGER_ARROW,
						isDirection_left ? 2 - slideOffset : slideOffset);
			} else if (drawerView == right_drawer) {// 根据isDirection_right决定执行动画
				mMaterialMenuIcon.setTransformationOffset(
						MaterialMenuDrawable.AnimationState.BURGER_ARROW,
						isDirection_right ? 2 - slideOffset : slideOffset);
			}
		}

		/**
		 * 当导航菜单打开时执行
		 */
		@Override
		public void onDrawerOpened(android.view.View drawerView) {
			if (drawerView == mMenuListView) {
				isDirection_left = true;
			} else if (drawerView == right_drawer) {
				isDirection_right = true;
			}
		}

		/**
		 * 当导航菜单关闭时执行
		 */
		@Override
		public void onDrawerClosed(android.view.View drawerView) {
			if (drawerView == mMenuListView) {
				isDirection_left = false;
			} else if (drawerView == right_drawer) {
				isDirection_right = false;
				showView = mMenuListView;
			}
		}
	}

	/**
	 * 切换主视图区域的Fragment
	 *
	 * @param position
	 */
	private void selectItem(int position) {
		Fragment fragment = new ContentFragment();
		Bundle args = new Bundle();
		switch (position) {
		case 0:
			args.putString("key", mMenuTitles[position]);
			break;
		case 1:
			args.putString("key", mMenuTitles[position]);
			break;
		case 2:
			args.putString("key", mMenuTitles[position]);
			break;
		case 3:
			args.putString("key", mMenuTitles[position]);
			break;
		default:
			break;
		}
		fragment.setArguments(args); // FragmentActivity将点击的菜单列表标题传递给Fragment
		FragmentManager fragmentManager = getSupportFragmentManager();
		fragmentManager.beginTransaction()
				.replace(R.id.content_frame, fragment).commit();

		// 更新选择后的item和title,然后关闭菜单
		mMenuListView.setItemChecked(position, true);
		setTitle(mMenuTitles[position]);
		mDrawerLayout.closeDrawer(mMenuListView);
	}

	/**
	 * 点击ActionBar上菜单
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
		switch (id) {
		case android.R.id.home:
			if (showView == mMenuListView) {
				if (!isDirection_left) { // 左边栏菜单关闭时,打开
					mDrawerLayout.openDrawer(mMenuListView);
				} else {// 左边栏菜单打开时,关闭
					mDrawerLayout.closeDrawer(mMenuListView);
				}
			} else if (showView == right_drawer) {
				if (!isDirection_right) {// 右边栏关闭时,打开
					mDrawerLayout.openDrawer(right_drawer);
				} else {// 右边栏打开时,关闭
					mDrawerLayout.closeDrawer(right_drawer);
				}
			}
			break;
		case R.id.action_personal:
			if (!isDirection_right) {// 右边栏关闭时,打开
				if (showView == mMenuListView) {
					mDrawerLayout.closeDrawer(mMenuListView);
				}
				mDrawerLayout.openDrawer(right_drawer);
			} else {// 右边栏打开时,关闭
				mDrawerLayout.closeDrawer(right_drawer);
			}
			break;
		default:
			break;
		}
		return super.onOptionsItemSelected(item);
	}

	/**
	 * 根据onPostCreate回调的状态,还原对应的icon state
	 */
	@Override
	protected void onPostCreate(Bundle savedInstanceState) {
		super.onPostCreate(savedInstanceState);
		mMaterialMenuIcon.syncState(savedInstanceState);
	}

	/**
	 * 根据onSaveInstanceState回调的状态,保存当前icon state
	 */
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		mMaterialMenuIcon.onSaveInstanceState(outState);
		super.onSaveInstanceState(outState);
	}

	/**
	 * 加载菜单
	 */
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}

源码请在这里下载

时间: 2024-08-06 11:58:17

Android组件——使用DrawerLayout仿网易新闻v4.4侧滑菜单的相关文章

Android 使用Drawerlayout仿网易新闻客户端抽屉模式

个人感觉网易的客户端比较前卫,有很多新鲜的东西,有时候模仿这些好的客户端能学到很多东西 开始今天的主要课题,下面是网易客户端抽屉模式实现的效果 其实有个Drawerlayout这个布局,你得问题就已经解决掉一大半了,Drawerlayout布局本身就提供了左划和右划的功能 先上代码,然后慢慢解答,看完这篇博客你就知道Drawerlayout怎么用了 首先上逐步局文件代码 <android.support.v4.widget.DrawerLayout xmlns:android="http:

【FastDev4Android框架开发】Android Design支持库TabLayout打造仿网易新闻Tab标签效果(三十七)

转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/50158985 本文出自:[江清清的博客] (一).前言: 仿36Kr客户端开发过程中,因为他们网站上面的新闻文章分类比较多,所以我这边还是打算模仿网易新闻APP的主界面新闻标签Tab以及页面滑动效果来进行实现.要实现的顶部的Tab标签的效果有很多方法例如采用开源项目ViewPagerIndicator中的TabPageIndicator就可以实现.不过我们今天不讲V

Android应用经典主界面框架之二:仿网易新闻client、CSDN client (Fragment ViewPager)

另外一种主界面风格则是以网易新闻.凤凰新闻以及新推出的新浪博客(阅读版)为代表.使用ViewPager+Fragment,即ViewPager里适配器里放的不是一般的View.而是Fragment.所以适配器不能继承PagerAdapter,而要继承FragmentPagerAdapter,这是在android.support.v4.app.FragmentPagerAdapter包里的.有点奇葩的是,FragmentPagerAdapter仅仅在这个包里有,在android.app.*这个包以

Android 开源框架ViewPageIndicator 和 ViewPager 仿网易新闻客户端Tab标签

之前用JakeWharton的开源框架ActionBarSherlock和ViewPager实现了对网易新闻客户端Tab标签的功能,ActionBarSherlock是在3.0以下的机器支持ActionBar的功能,有兴趣的可以看看开源框架ActionBarSherlock 和 ViewPager 仿网易新闻客户端,今天用到的是JakeWharton的另一开源控件ViewPageIndicator,ViewPager想必大家都知道,Indicator指示器的意思,所以ViewPageIndica

Android 开源框架ViewPageIndicator 和 ViewPager 仿网易新闻clientTab标签

之前用JakeWharton的开源框架ActionBarSherlock和ViewPager实现了对网易新闻clientTab标签的功能,ActionBarSherlock是在3.0下面的机器支持ActionBar的功能,有兴趣的能够看看开源框架ActionBarSherlock 和 ViewPager 仿网易新闻client,今天用到的是JakeWharton的还有一开源控件ViewPageIndicator.ViewPager想必大家都知道,Indicator指示器的意思,所以ViewPag

Android应用经典主界面框架之二:仿网易新闻客户端、CSDN 客户端 (Fragment ViewPager)

第二种主界面风格则是以网易新闻.凤凰新闻以及新推出的新浪博客(阅读版)为代表,使用ViewPager+Fragment,即ViewPager里适配器里放的不是一般的View,而是Fragment.所以适配器不能继承PagerAdapter,而要继承FragmentPagerAdapter,这是在android.support.v4.app.FragmentPagerAdapter包里的.有点奇葩的是,FragmentPagerAdapter只在这个包里有,在android.app.*这个包下面么

Android 开源框架ActionBarSherlock 和 ViewPager 仿网易新闻客户端

转载请注明出处:http://blog.csdn.net/xiaanming/article/details/9971721 大家都知道Android的ActionBar是在3.0以上才有的,那么在3.0以下呢,google并没有给我提供在3.0以下支持ActionBar的包,但是外国的大牛JakeWharton实现了在3.0以下使用ActionBar, JakeWharton这位大牛是ActionBarSherlock,Android-ViewPagerIndicator ,NineOldAn

android 仿网易新闻客户端源码都有

原文:android 仿网易新闻客户端源码都有 android 仿网易新闻服务端源码 源代码下载地址: http://www.zuidaima.com/share/1550463560944640.htm http://www.zuidaima.com/share/1550463561206784.htm android 仿网易新闻 客户端和服务端 源码都有 ,有些功能还未实现,因为文件有点大,所以分为2次上传  java源代码截图:

关于仿网易新闻中详细页图文混排功能的实现

最近在了解关于新闻内容的图文混排的效果,网上有人开源一个仿网易新闻的代码,本文就是简单记录学习其详细页面显示的效果实现: 下载地址:https://github.com/dsxNiubility/SXNews 效果图: 其原理:通过网络请求获得相关的信息,再通过手机端进行拼HTML,然后在WebView进行展示,此处还对文章中的图片增加点击效果,可以保存到相册中:文章的样式已经存在项目中,直接去调用: 1:首先了解两个相关的实体对象,一个是新闻的主体内容,另外一个就是图片的相关信息实体: 1:主