Android新闻客户端开发

一、前言

      新闻客户端相信大家都用过,很多开发者对于新闻客户端的主界面很感兴趣,想自己开发一个。

二、源码

     主要是使用了SlidingMenu这样一个自定义控件,实现左边和右边都能滑动出菜单界面,而主界面是使用的viewFlipper控件。滑动的菜单和主界面都为fragment

1、SlidingMenu控件代码:

public class SlidingMenu extends RelativeLayout {

	private View mSlidingView;
	// private View mMenuView;// 左边菜单view
	private View mDetailView;// 右边消息view
	private RelativeLayout bgShade;
	private int screenWidth;
	private int screenHeight;
	private Context mContext;
	private Scroller mScroller;
	private VelocityTracker mVelocityTracker;
	private int mTouchSlop;
	private float mLastMotionX;
	private float mLastMotionY;
	private static final int VELOCITY = 50;
	private boolean mIsBeingDragged = true;
	private boolean tCanSlideLeft = true;
	private boolean tCanSlideRight = false;
	private boolean hasClickLeft = false;
	private boolean hasClickRight = false;

	public SlidingMenu(Context context) {
		super(context);
		init(context);
	}

	private void init(Context context) {

		mContext = context;
		bgShade = new RelativeLayout(context);
		mScroller = new Scroller(getContext());
		mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
		WindowManager windowManager = ((Activity) context).getWindow().getWindowManager();
		Display display = windowManager.getDefaultDisplay();
		screenWidth = display.getWidth();
		screenHeight = display.getHeight();
		LayoutParams bgParams = new LayoutParams(screenWidth, screenHeight);
		bgParams.addRule(RelativeLayout.CENTER_IN_PARENT);
		bgShade.setLayoutParams(bgParams);

	}

	public SlidingMenu(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	// 暂时无用
	public void addViews(View left, View center, View right) {
		// setLeftView(left);
		setRightView(right);
		setCenterView(center);
	}

	// 设置左边view
	// public void setLeftView(View view) {
	// LayoutParams behindParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
	// LayoutParams.MATCH_PARENT);
	// addView(view, behindParams);
	// mMenuView = view;
	// }
	//
	// public View getLeftView() {
	// return mMenuView;
	// }

	public View getRightView() {
		return mDetailView;
	}

	// 设置右边view
	public void setRightView(View view) {
		LayoutParams behindParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
				LayoutParams.MATCH_PARENT);
		behindParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
		addView(view, behindParams);
		mDetailView = view;
	}

	// 设置中间view
	public void setCenterView(View view) {
		LayoutParams aboveParams = new LayoutParams(LayoutParams.MATCH_PARENT,
				LayoutParams.MATCH_PARENT);

		LayoutParams bgParams = new LayoutParams(screenWidth, screenHeight);
		bgParams.addRule(RelativeLayout.CENTER_IN_PARENT);

		View bgShadeContent = new View(mContext);
		bgShadeContent.setBackgroundResource(R.drawable.shade_bg);
		bgShade.addView(bgShadeContent, bgParams);

		addView(bgShade, bgParams);

		addView(view, aboveParams);
		mSlidingView = view;
		mSlidingView.bringToFront();
	}

	@Override
	public void scrollTo(int x, int y) {
		super.scrollTo(x, y);
		postInvalidate();
	}

	@Override
	public void computeScroll() {
		if (!mScroller.isFinished()) {
			if (mScroller.computeScrollOffset()) {
				int oldX = mSlidingView.getScrollX();
				int oldY = mSlidingView.getScrollY();
				int x = mScroller.getCurrX();
				int y = mScroller.getCurrY();
				if (oldX != x || oldY != y) {
					if (mSlidingView != null) {
						mSlidingView.scrollTo(x, y);
						if (x < 0)
							bgShade.scrollTo(x + 10, y);// 背景阴影右偏
						else
							bgShade.scrollTo(x - 10, y);// 背景阴影左偏
					}
				}
				invalidate();
			}
		}
	}

	private boolean canSlideLeft = true;// 是否能向左滑动
	private boolean canSlideRight = false;// 是否能向右滑动

	public void setCanSliding(boolean left, boolean right) {
		canSlideLeft = left;
		canSlideRight = right;
	}

	/* 拦截touch事件 */
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		final int action = ev.getAction();
		final float x = ev.getX();
		final float y = ev.getY();
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			// showToast("MotionEvent.ACTION_DOWN....");
			mLastMotionX = x;
			mLastMotionY = y;
			mIsBeingDragged = false;
			if (canSlideLeft) {
				// mMenuView.setVisibility(View.VISIBLE);
				mDetailView.setVisibility(View.INVISIBLE);
			}
			if (canSlideRight) {
				// mMenuView.setVisibility(View.INVISIBLE);
				mDetailView.setVisibility(View.VISIBLE);
			}
			break;

		case MotionEvent.ACTION_MOVE:
			// showToast("MotionEvent.ACTION_MOVE....");
			final float dx = x - mLastMotionX;
			final float xDiff = Math.abs(dx);
			final float yDiff = Math.abs(y - mLastMotionY);
			if (xDiff > mTouchSlop && xDiff > yDiff) {
				if (canSlideLeft) {
					float oldScrollX = mSlidingView.getScrollX();
					if (oldScrollX < 0) {
						mIsBeingDragged = true;
						mLastMotionX = x;
					} else {
						if (dx > 0) {
							mIsBeingDragged = true;
							mLastMotionX = x;
						}
					}
				} else if (canSlideRight) {
					float oldScrollX = mSlidingView.getScrollX();
					if (oldScrollX > 0) {
						mIsBeingDragged = true;
						mLastMotionX = x;
					} else {
						if (dx < 0) {
							mIsBeingDragged = true;
							mLastMotionX = x;
						}
					}
				}
			}
			break;

		}
		return mIsBeingDragged;
	}

	/* 处理拦截后的touch事件 */
	@SuppressLint("Recycle")
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		if (mVelocityTracker == null) {
			mVelocityTracker = VelocityTracker.obtain();
		}
		mVelocityTracker.addMovement(ev);

		final int action = ev.getAction();
		final float x = ev.getX();
		final float y = ev.getY();

		switch (action) {
		case MotionEvent.ACTION_DOWN:
			if (!mScroller.isFinished()) {
				mScroller.abortAnimation();
			}
			mLastMotionX = x;
			mLastMotionY = y;
			if (mSlidingView.getScrollX() == -getMenuViewWidth()
					&& mLastMotionX < getMenuViewWidth()) {
				return false;
			}

			if (mSlidingView.getScrollX() == getDetailViewWidth()
					&& mLastMotionX > getMenuViewWidth()) {
				return false;
			}

			break;
		case MotionEvent.ACTION_MOVE:
			if (mIsBeingDragged) {
				final float deltaX = mLastMotionX - x;
				mLastMotionX = x;
				float oldScrollX = mSlidingView.getScrollX();
				float scrollX = oldScrollX + deltaX;
				if (canSlideLeft) {
					if (scrollX > 0)
						scrollX = 0;
				}
				if (canSlideRight) {
					if (scrollX < 0)
						scrollX = 0;
				}
				if (deltaX < 0 && oldScrollX < 0) { // left view
					final float leftBound = 0;
					final float rightBound = -getMenuViewWidth();
					if (scrollX > leftBound) {
						scrollX = leftBound;
					} else if (scrollX < rightBound) {
						scrollX = rightBound;
					}
				} else if (deltaX > 0 && oldScrollX > 0) { // right view
					final float rightBound = getDetailViewWidth();
					final float leftBound = 0;
					if (scrollX < leftBound) {
						scrollX = leftBound;
					} else if (scrollX > rightBound) {
						scrollX = rightBound;
					}
				}
				if (mSlidingView != null) {
					mSlidingView.scrollTo((int) scrollX, mSlidingView.getScrollY());
					if (scrollX < 0) {// Left View
						bgShade.scrollTo((int) scrollX + 10, mSlidingView.getScrollY());
					} else {// Right View
						bgShade.scrollTo((int) scrollX - 10, mSlidingView.getScrollY());
					}
				}

			}
			break;
		case MotionEvent.ACTION_CANCEL:
		case MotionEvent.ACTION_UP:
			if (mIsBeingDragged) {
				final VelocityTracker velocityTracker = mVelocityTracker;
				velocityTracker.computeCurrentVelocity(100);
				float xVelocity = velocityTracker.getXVelocity();// 滑动的速度
				int oldScrollX = mSlidingView.getScrollX();
				int dx = 0;
				if (oldScrollX <= 0 && canSlideLeft) {// left view
					if (xVelocity > VELOCITY) {
						dx = -getMenuViewWidth() - oldScrollX;
					} else if (xVelocity < -VELOCITY) {
						dx = -oldScrollX;
						if (hasClickLeft) {
							hasClickLeft = false;
							setCanSliding(tCanSlideLeft, tCanSlideRight);
						}
					} else if (oldScrollX < -getMenuViewWidth() / 2) {
						dx = -getMenuViewWidth() - oldScrollX;
					} else if (oldScrollX >= -getMenuViewWidth() / 2) {
						dx = -oldScrollX;
						if (hasClickLeft) {
							hasClickLeft = false;
							setCanSliding(tCanSlideLeft, tCanSlideRight);
						}
					}

				}
				if (oldScrollX >= 0 && canSlideRight) {
					if (xVelocity < -VELOCITY) {
						dx = getDetailViewWidth() - oldScrollX;
					} else if (xVelocity > VELOCITY) {
						dx = -oldScrollX;
						if (hasClickRight) {
							hasClickRight = false;
							setCanSliding(tCanSlideLeft, tCanSlideRight);
						}
					} else if (oldScrollX > getDetailViewWidth() / 2) {
						dx = getDetailViewWidth() - oldScrollX;
					} else if (oldScrollX <= getDetailViewWidth() / 2) {
						dx = -oldScrollX;
						if (hasClickRight) {
							hasClickRight = false;
							setCanSliding(tCanSlideLeft, tCanSlideRight);
						}
					}
				}
				smoothScrollTo(dx);
			}

			break;
		}

		return true;
	}

	public int getMenuViewWidth() {
		// if (mMenuView == null) {
		return 0;
		// }
		// return mMenuView.getWidth();
	}

	public int getDetailViewWidth() {
		if (mDetailView == null) {
			return 0;
		}
		return mDetailView.getWidth();
	}

	void smoothScrollTo(int dx) {
		int duration = 500;
		int oldScrollX = mSlidingView.getScrollX();
		mScroller.startScroll(oldScrollX, mSlidingView.getScrollY(), dx, mSlidingView.getScrollY(),
				duration);
		if (oldScrollX < 0) {// Left
			if (dx <= 0) {// Left 显示
				showLeft = true;
			} else {
				showLeft = false;
			}
		} else {// Right
			if (dx >= 0) {// Right 显示
				showRight = true;
			} else {
				showRight = false;
			}
		}
		invalidate();
	}

	public boolean showLeft = false;

	/*
	 * 显示左侧边的view
	 */
	// public void showLeftView() {
	// // int menuWidth = mMenuView.getWidth();
	// int oldScrollX = mSlidingView.getScrollX();
	// if (oldScrollX == 0) {
	// mMenuView.setVisibility(View.VISIBLE);
	// mDetailView.setVisibility(View.INVISIBLE);
	// smoothScrollTo(-menuWidth);
	// tCanSlideLeft = canSlideLeft;
	// tCanSlideRight = canSlideRight;
	// hasClickLeft = true;
	// setCanSliding(true, false);
	// showLeft = true;
	// } else if (oldScrollX == -menuWidth) {
	// smoothScrollTo(menuWidth);
	// showLeft = false;
	// if (hasClickLeft) {
	// hasClickLeft = false;
	// setCanSliding(tCanSlideLeft, tCanSlideRight);
	// }
	// }
	// }

	public boolean showRight = false;

	/* 显示右侧边的view */
	public void showRightView() {
		int menuWidth = mDetailView.getWidth();
		int oldScrollX = mSlidingView.getScrollX();
		if (oldScrollX == 0) {
			// mMenuView.setVisibility(View.INVISIBLE);
			mDetailView.setVisibility(View.VISIBLE);
			smoothScrollTo(menuWidth);
			tCanSlideLeft = canSlideLeft;
			tCanSlideRight = canSlideRight;
			hasClickRight = true;
			showRight = true;
			showLeft = false;
			setCanSliding(false, true);
		} else if (oldScrollX == menuWidth) {
			smoothScrollTo(-menuWidth);
			showRight = false;
			if (hasClickRight) {
				hasClickRight = false;
				setCanSliding(tCanSlideLeft, tCanSlideRight);
			}
		}
	}

	public boolean getLeftVisbility() {
		return showLeft;
	}

	public boolean getRightVisbility() {
		return showRight;
	}

}

说明:因为我这个客户端只能右边显示出菜单,所以对代码进行了修改,如上注释部分的代码。 

2、布局文件

2.1 mainActivity布局

<SlidingMenu xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/slidingMenu"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

 2.2 右边菜单和主界面布局是一样的

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/right_frame"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />

2.3 mainFragment布局

<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >
    <include layout="@layout/title"/>
    <LinearLayout 
        android:id="@+id/linearLayout1" 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:paddingBottom="5dip" 
        android:paddingTop="10dip" 
        android:background="@color/lightgrey"
        android:orientation="horizontal"
        >
    <TextView 
         android:id="@+id/tab_history" 
         android:layout_width="match_parent" 
         android:layout_height="match_parent" 
         android:layout_weight="1.0" 
         android:gravity="center" 
         android:text="@string/tab1" 
         android:textColor="@color/white" 
         android:textSize="15sp"/>
     <TextView 
         android:id="@+id/tab_knowlodge" 
         android:layout_width="match_parent" 
         android:layout_height="match_parent" 
         android:layout_weight="1.0" 
         android:gravity="center" 
         android:text="@string/tab2" 
         android:textColor="@color/blue" 
         android:textSize="15sp"/>
     <TextView 
         android:id="@+id/tab_joker" 
         android:layout_width="match_parent" 
         android:layout_height="match_parent" 
         android:layout_weight="1.0" 
         android:gravity="center" 
         android:text="@string/tab3" 
         android:textColor="@color/blue" 
         android:textSize="15sp"/>
<!--      <TextView  -->
<!--          android:id="@+id/tab_star"  -->
<!--          android:layout_width="match_parent"  -->
<!--          android:layout_height="match_parent"  -->
<!--          android:layout_weight="1.0"  -->
<!--          android:gravity="center"  -->
<!--          android:text="@string/tab_4"  -->
<!--          android:textColor="@color/blue"  -->
<!--          android:textSize="15sp"/> -->
</LinearLayout>

<!-- <LinearLayout  -->
<!--     android:layout_width="match_parent"  -->
<!--     android:layout_height="wrap_content"  -->
<!--     android:layout_gravity="bottom"  -->
<!--     android:orientation="vertical"  -->
<!--     android:paddingBottom="3dip"> -->
 
<ImageView 
    android:id="@+id/iv_bottom_line" 
    android:layout_width="40dip" 
    android:layout_height="2dip" 
    android:layout_marginLeft="40dip" 
    android:scaleType="matrix"
    android:contentDescription="@null" 
    android:src="#fff">
        </ImageView>
<!-- </LinearLayout> -->
    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        />
</LinearLayout>

3、mainFragment源码

public class MainFragment extends Fragment implements ViewPager.OnPageChangeListener,
		OnClickListener {

	private ViewPager viewPager;

	private List<Fragment> fragments;

	private TextView historyText, jokerText, knowledgeText;

	private ImageView lineImage;

	private ImageButton mUserBtn, mCommentBtn;

	private int currIndex = 0;

	private float position_one, position_two;

	private OnShowLeftListener mListener;

	public interface OnShowLeftListener {
		public void showLeftFragment();
	}

	public static MainFragment instance() {
		return new MainFragment();
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		View view = inflater.inflate(R.layout.fragment_main, container, false);
		init(view);
		return view;
	}

	private void init(View view) {
		viewPager = (ViewPager) view.findViewById(R.id.viewPager);
		fragments = new ArrayList<Fragment>();
		fragments.add(NewsFragment.instance());// 添加客户端主界面所有的fragment
		fragments.add(InfoFragment.instance());
		fragments.add(StategyFragment.instance());
		ViewAdapter adapter = new ViewAdapter(getFragmentManager(), fragments);
		viewPager.setAdapter(adapter);
		viewPager.setCurrentItem(0);
		viewPager.setOnPageChangeListener(this);

		historyText = (TextView) view.findViewById(R.id.tab_history);
		jokerText = (TextView) view.findViewById(R.id.tab_joker);
		knowledgeText = (TextView) view.findViewById(R.id.tab_knowlodge);
		historyText.setOnClickListener(this);
		jokerText.setOnClickListener(this);
		knowledgeText.setOnClickListener(this);
		lineImage = (ImageView) view.findViewById(R.id.iv_bottom_line);
		// int bottomLineWidth = lineImage.getLayoutParams().width;
		DisplayMetrics dm = new DisplayMetrics();
		getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
		int screenW = dm.widthPixels;
		position_one = (float) screenW / (fragments.size());

		position_two = position_one * 2;
		// position_three = position_one * 3;
		mUserBtn = (ImageButton) view.findViewById(R.id.button_user);
		mUserBtn.setOnClickListener(this);
		mCommentBtn = (ImageButton) view.findViewById(R.id.button_comment);
		mCommentBtn.setOnClickListener(this);
		mCommentBtn.setVisibility(View.GONE);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
	}

	@Override
	public void onStart() {
		super.onStart();
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.tab_history:
			viewPager.setCurrentItem(0);
			break;
		case R.id.tab_joker:
			viewPager.setCurrentItem(2);
			break;
		// case R.id.tab_star:
		// if (checkUser())
		// viewPager.setCurrentItem(3);
		// break;
		case R.id.tab_knowlodge:
			viewPager.setCurrentItem(1);
			break;
		case R.id.button_user:
			mListener.showLeftFragment();
			break;
		case R.id.button_comment:
			// appwall.doShowAppWall();
			break;
		default:
			viewPager.setCurrentItem(0);
			break;
		}
	}

	@Override
	public void onPageScrollStateChanged(int arg0) {
	}

	@Override
	public void onPageScrolled(int arg0, float arg1, int arg2) {
	}

	@Override
	public void onPageSelected(int arg0) {
		Animation animation = null;
		switch (arg0) {
		case 0:
			if (currIndex == 1) {
				animation = new TranslateAnimation(position_one, 0, 0, 0);
				knowledgeText.setTextColor(getResources().getColor(R.color.blue));
			} else if (currIndex == 2) {
				animation = new TranslateAnimation(position_two, 0, 0, 0);
				jokerText.setTextColor(getResources().getColor(R.color.blue));
			}
			// else if (currIndex == 3) {
			// animation = new TranslateAnimation(position_three, 0, 0, 0);
			// starText.setTextColor(getResources().getColor(R.color.blue));
			// }
			historyText.setTextColor(getResources().getColor(R.color.white));
			break;
		case 1:
			if (currIndex == 0) {
				animation = new TranslateAnimation(0, position_one, 0, 0);
				historyText.setTextColor(getResources().getColor(R.color.blue));
			} else if (currIndex == 2) {
				animation = new TranslateAnimation(position_two, position_one, 0, 0);
				jokerText.setTextColor(getResources().getColor(R.color.blue));
			}
			// else if (currIndex == 3) {
			// animation = new TranslateAnimation(position_three, position_one, 0, 0);
			// starText.setTextColor(getResources().getColor(R.color.blue));
			// }
			knowledgeText.setTextColor(getResources().getColor(R.color.white));
			break;
		case 2:
			if (currIndex == 0) {
				animation = new TranslateAnimation(0, position_two, 0, 0);
				historyText.setTextColor(getResources().getColor(R.color.blue));
			} else if (currIndex == 1) {
				animation = new TranslateAnimation(position_one, position_two, 0, 0);
				knowledgeText.setTextColor(getResources().getColor(R.color.blue));
			}
			// else if (currIndex == 3) {
			// animation = new TranslateAnimation(position_three, position_two, 0, 0);
			// starText.setTextColor(getResources().getColor(R.color.blue));
			// }
			jokerText.setTextColor(getResources().getColor(R.color.white));
			break;
		// case 3:
		// if (checkUser()) {
		// if (currIndex == 0) {
		// animation = new TranslateAnimation(0, position_three, 0, 0);
		// historyText.setTextColor(getResources().getColor(R.color.blue));
		// } else if (currIndex == 1) {
		// animation = new TranslateAnimation(position_one, position_three, 0, 0);
		// knowledgeText.setTextColor(getResources().getColor(R.color.blue));
		// } else if (currIndex == 2) {
		// animation = new TranslateAnimation(position_two, position_three, 0, 0);
		// jokerText.setTextColor(getResources().getColor(R.color.blue));
		// }
		// starText.setTextColor(getResources().getColor(R.color.white));
		// }
		// break;
		}
		if (animation != null) {
			currIndex = arg0;
			animation.setFillAfter(true);
			animation.setDuration(300);
			lineImage.startAnimation(animation);
		}
	}

	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);
		mListener = (OnShowLeftListener) activity;
	}

}

4、mainActivity源码

public class MainActivity extends FragmentActivity implements MainFragment.OnShowLeftListener {

	private SlidingMenu mSlidingMenu;

	private MainFragment mMainFrag;

	private UserFragment mUserFrag;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mSlidingMenu = (SlidingMenu) findViewById(R.id.slidingMenu);
		mSlidingMenu.setRightView(getLayoutInflater().inflate(R.layout.right_frame, null));
		mSlidingMenu.setCenterView(getLayoutInflater().inflate(R.layout.center_frame, null));
		FragmentTransaction t = this.getSupportFragmentManager().beginTransaction();
		mMainFrag = MainFragment.instance();
		t.replace(R.id.center_frame, mMainFrag);
		mUserFrag = UserFragment.instance();
		t.replace(R.id.right_frame, mUserFrag);
		t.commit();
		mSlidingMenu.setCanSliding(false, true);
	}

	
	@Override
	protected void onPause() {
		super.onPause();
			}

	@Override
	protected void onResume() {
		super.onResume();
			}

	@Override
	public void showLeftFragment() {
		mSlidingMenu.showRightView();
	}

}

三、总结

以上基本上就是一个客户端的主界面开发,欢迎大家去下载我自己开发的一个新闻客户端,谢谢大家!

http://android.myapp.com/myapp/detail.htm?apkName=com.yln.history

精彩科技工作室

猜你喜欢

转载自yaolinnan.iteye.com/blog/2177143