프로그래밍/Android

안드로이드 아름다운 카드뷰(Card View) 리스트 만들기 - (3)

Lou Park 2016. 6. 17. 22:58

이번 강의에서는 Card View에 이미지를 적용 시키는 방법과, 개별 클릭 이벤트를 처리하는 방법에 대해 알아 볼 것이다.

나는 이미지 URL을 이용해 이미지를 불러올 것이기 때문에 마음 편하게 라이브러리를 사용했다.

이미지 관련 라이브러리 중 유명한 것은 Picasso와 Glide가 있는데, 둘 다 사용법은 비슷하고 성능도 좋다.


이미지 라이브러리인 Picasso를 사용하기 위해

Gradle에 다음 코드를 한 줄 추가한다.


build.gradle (Module : app)

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.android.support:cardview-v7:23.0.+'
compile 'com.android.support:recyclerview-v7:23.0.+'
compile 'com.squareup.picasso:picasso:2.5.2' //this line !
}

그러면 이제 picasso 라이브러리를 사용할 수 있게 된다.

다시 NoticeAdapter.java로 들어가서 이제 이미지 관련 처리를 해보자.


NoticeAdapter.java

package com.example.jizard.testapplication.adapter;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.example.jizard.testapplication.NoticeActivity;
import com.example.jizard.testapplication.R;
import com.example.jizard.testapplication.datatype.NoticeData;
import com.squareup.picasso.Picasso;

import java.util.ArrayList;
import java.util.HashMap;

/**
* Created by gold24park on 2016. 4. 4..
*/
public class NoticeAdapter extends RecyclerView.Adapter<NoticeAdapter.ViewHolder> {
Context context;
ArrayList<NoticeData> noticeList; //공지사항 정보 담겨있음

public NoticeAdapter(Context context, ArrayList<NoticeData> noticeList) {
Log.e("[IMPORTANT] ", "init size" + noticeList.size());
this.context = context;
this.noticeList = noticeList;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//recycler view에 반복될 아이템 레이아웃 연결
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_notice,null);
return new ViewHolder(v);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
/** 정보 및 이벤트 처리는 이 메소드에서 구현 **/
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
NoticeData noticeData = noticeList.get(position);
final int pos = position;
//정보 다듬기
String content = noticeData.content;
String title = noticeData.title;
if(content.length() > 50 ) {
content = content.substring(0,50) + "..."; //50자 자르고 ... 붙이기
}
if(title.length() > 16 ) {
title = title.substring(0,16) + "..."; //18자 자르고 ... 붙이기
}
//정보 세팅해서 출력
if(noticeData.img1.isEmpty()) {
holder.rl_image.setVisibility(View.GONE);
} else {
//resize = pixel
Picasso.with(context).load(noticeData.img1).into(holder.iv_image);
}
holder.tv_writer.setText(noticeData.writer); //작성자
holder.tv_title.setText(title); //제목
holder.tv_content.setText(content); //내용 일부
holder.tv_date.setText(noticeData.date); //작성일
holder.tv_count.setText(noticeData.count); //댓글 수
holder.cv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(context, NoticeActivity.class);
i.putExtra("writer", noticeList.get(pos).writer);
i.putExtra("title", noticeList.get(pos).title);
i.putExtra("content", noticeList.get(pos).content);
i.putExtra("regist_day", noticeList.get(pos).date);
i.putExtra("r_count", noticeList.get(pos).count);
i.putExtra("cnum", noticeList.get(pos).cnum);
i.putExtra("img1", noticeList.get(pos).img1);
i.putExtra("img2", noticeList.get(pos).img2);
i.putExtra("img3", noticeList.get(pos).img3);
i.putExtra("id", noticeList.get(pos).id);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
});
}

@Override
public int getItemCount() {
return this.noticeList.size();
}
/** item layout 불러오기 **/
public class ViewHolder extends RecyclerView.ViewHolder {
TextView tv_title;
TextView tv_date;
TextView tv_content;
TextView tv_writer;
TextView tv_count;
CardView cv;
ImageView iv_image;
RelativeLayout rl_image;

public ViewHolder(View v) {
super(v);
tv_title = (TextView) v.findViewById(R.id.tv_title);
tv_date = (TextView) v.findViewById(R.id.tv_date);
tv_content = (TextView) v.findViewById(R.id.tv_content);
tv_writer = (TextView) v.findViewById(R.id.tv_writer);
tv_count = (TextView) v.findViewById(R.id.tv_count);
cv = (CardView) v.findViewById(R.id.cv);
iv_image = (ImageView) v.findViewById(R.id.iv_image);
rl_image = (RelativeLayout) v.findViewById(R.id.rl_image);
}
}
}

이미지 구현과 관련된 부분은 검은색 줄 처리된 부분이다. (못생기게 줄그어서 죄송합니다!!!)

지난 강의에서와는 다르게 noticeData를 쓰고 있는데..리팩토링한지 오래되서...뭐 기억은 안나지만

아무튼 noticeData.img1이란건 이미지 URL을 담고있는 String이다.

즉, 이미지 URL이 없으면 이미지 뷰를 숨기고, 있다면 해당 이미지를 이미지뷰에 보여주는게 된다.


item_notice.xml

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/rl_image">

<ImageView
android:layout_width="fill_parent"
android:layout_height="200dp"
android:id="@+id/iv_image"
android:src="@drawable/ic_arrow_right"
android:scaleType="centerCrop" />
</RelativeLayout>

item_notice에서는 이미지뷰를 다음과같이 centerCrop하고 있다.


아이템클릭과 관련한 부분은 NoticeAdapter.java에서 회색 줄 처리된 부분이다.

개별 아이템 마다 OnClickListener를 만들어 인텐트로 값을 넘기고,

다음 액티비티인 NoticeActivity로 넘어갈 수 있도록 한다.


NoticeActivity에서는 NoticeAdapter에서 보낸 intent정보를 받고

뷰에 뿌려주기만 하면 된다. 그러면 카드뷰 완성!


NoticeActivity.java

package com.example.jizard.testapplication;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.example.jizard.testapplication.adapter.ReplyListAdapter;
import com.example.jizard.testapplication.datatype.ReplyData;
import com.example.jizard.testapplication.parser.ReplyParser;
import com.squareup.picasso.Picasso;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ExecutionException;

/**
* Created by gold24park on 2016. 4. 5..
*/
public class NoticeActivity extends Activity {

private final String TAG_TYPE = "notice";

private String title,writer,regist_day,r_count,content,img1,img2,img3;
private TextView tv_title,tv_content,tv_count,tv_writer,tv_date;
private ImageView iv_img1,iv_img2,iv_img3;
private View header;
private static ListView replyListView;
private static String cnum, id;
private static ReplyListAdapter replyListAdapter;
private static Context context;

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

try {
updateReplyList();
loadReplyFragment();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}

//뷰에 정보 세팅 & 출력
tv_title.setText(title);
tv_writer.setText(writer);
tv_date.setText(regist_day);
tv_content.setText(content);
tv_count.setText(r_count);

loadImage1(img1);
loadImage2(img2);
loadImage3(img3);

iv_img1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(context, ImageActivity.class);
i.putExtra("img", img1);
startActivity(i);
}
});
iv_img2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(context,ImageActivity.class);
i.putExtra("img",img2);
startActivity(i);
}
});
iv_img3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(context, ImageActivity.class);
i.putExtra("img", img3);
startActivity(i);
}
});
}

public static void updateReplyList() throws ExecutionException, InterruptedException {
String url = "http://pho901121.cafe24.com/login/db_get_reply.php?cnum=" + cnum + "&id=" + id;
ReplyParser replyParser = new ReplyParser(context);
ArrayList<ReplyData> replyList = replyParser.execute(url).get();
replyListAdapter = new ReplyListAdapter(context, replyList);
replyListView.setAdapter(replyListAdapter);
replyListAdapter.notifyDataSetChanged();
}

public void loadReplyFragment() {
HashMap<String, String> postInfomation = new HashMap<String, String>();
postInfomation.put("id", id);
postInfomation.put("cnum", cnum);
postInfomation.put("type", TAG_TYPE);

Fragment fragment = new ReplyFragment().addInformation(postInfomation);
final FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.ll_reply_fragment, fragment); //fragment 지운 후 add
transaction.commit();
}

public void loadImage1(String url) {
if(!url.isEmpty()) {
Picasso.with(this).load(url).into(iv_img1);
Toast.makeText(context, "image: " + url, Toast.LENGTH_SHORT).show();
}
}
public void loadImage2(String url) {
if(!url.isEmpty()) {
Picasso.with(this).load(url).into(iv_img2);
}
}
public void loadImage3(String url) {
if(!url.isEmpty()) {
Picasso.with(this).load(url).into(iv_img3);
}
}


public void init() {
context = getApplicationContext();
header = getLayoutInflater().inflate(R.layout.header_notice, null);
replyListView = (ListView) findViewById(R.id.lv_reply);
replyListView.addHeaderView(header);
tv_title = (TextView) header.findViewById(R.id.tv_title);
tv_writer = (TextView) header.findViewById(R.id.tv_writer);
tv_date = (TextView) header.findViewById(R.id.tv_date);
tv_count = (TextView) header.findViewById(R.id.tv_count);
tv_content = (TextView) header.findViewById(R.id.tv_content);
iv_img1 = (ImageView) header.findViewById(R.id.iv_img1);
iv_img2 = (ImageView) header.findViewById(R.id.iv_img2);
iv_img3 = (ImageView) header.findViewById(R.id.iv_img3);
}

public void receiveIntentData() {
Intent intent = getIntent();
title = intent.getStringExtra("title");
writer = intent.getStringExtra("writer");
regist_day = intent.getStringExtra("regist_day");
r_count = intent.getStringExtra("r_count");
content = intent.getStringExtra("content");
cnum = intent.getStringExtra("cnum");
img1 = intent.getStringExtra("img1");
img2 = intent.getStringExtra("img2");
img3 = intent.getStringExtra("img3");
id = intent.getStringExtra("id");
}
}